استفاده از حافظه برنامه خود را با Memory Profiler بررسی کنید

Memory Profiler یکی از اجزای Android Profiler است که به شما کمک می کند نشت حافظه و ریزش حافظه را شناسایی کنید که می تواند منجر به لکنت، فریز و حتی خرابی برنامه شود. این نمودار یک نمودار بیدرنگ از میزان استفاده از حافظه برنامه شما را نشان می دهد و به شما امکان می دهد یک پشته خالی را ضبط کنید، جمع آوری زباله را مجبور کنید، و تخصیص حافظه را پیگیری کنید.

برای باز کردن Memory Profiler، مراحل زیر را دنبال کنید:

  1. روی View > Tool Windows > Profiler کلیک کنید (همچنین می توانید روی Profile کلیک کنید در نوار ابزار).
  2. فرآیند دستگاه و برنامه مورد نظر را از نوار ابزار Android Profiler انتخاب کنید. اگر دستگاهی را از طریق USB وصل کرده اید اما آن را در لیست نمی بینید، مطمئن شوید که اشکال زدایی USB را فعال کرده اید.
  3. روی هر نقطه از جدول زمانی MEMORY کلیک کنید تا Memory Profiler باز شود.

همچنین، می‌توانید حافظه برنامه خود را از خط فرمان با dumpsys بررسی کنید و همچنین رویدادهای GC را در logcat ببینید .

چرا باید حافظه برنامه خود را نمایه کنید

Android یک محیط حافظه مدیریت شده را فراهم می کند - وقتی مشخص می کند که برنامه شما دیگر از برخی اشیاء استفاده نمی کند، زباله جمع کننده حافظه استفاده نشده را به پشته باز می کند. نحوه یافتن حافظه استفاده نشده اندروید به طور مداوم در حال بهبود است، اما در برخی از نسخه‌های اندروید، سیستم باید برای مدت کوتاهی کد شما را متوقف کند. بیشتر اوقات، مکث ها غیرقابل درک است. با این حال، اگر برنامه شما سریع‌تر از آنچه سیستم می‌تواند آن را جمع‌آوری کند، حافظه را تخصیص می‌دهد، ممکن است برنامه شما به تأخیر بیفتد در حالی که جمع‌آورنده حافظه کافی برای برآورده کردن تخصیص‌های شما آزاد می‌کند. تأخیر ممکن است باعث شود برنامه شما فریم ها را رد کند و باعث کندی قابل مشاهده شود.

حتی اگر برنامه شما کندی را نشان نمی‌دهد، اگر حافظه‌اش نشت کند، می‌تواند آن حافظه را حتی زمانی که در پس‌زمینه است حفظ کند. این رفتار می‌تواند با تحمیل رویدادهای جمع‌آوری زباله غیرضروری، بقیه عملکرد حافظه سیستم را کاهش دهد. در نهایت، سیستم مجبور می شود برای بازیابی حافظه، فرآیند برنامه شما را از بین ببرد. سپس وقتی کاربر به برنامه شما بازگشت، باید به طور کامل راه اندازی مجدد شود.

برای کمک به جلوگیری از این مشکلات، باید از Memory Profiler برای انجام کارهای زیر استفاده کنید:

  • به دنبال الگوهای تخصیص حافظه نامطلوب در جدول زمانی باشید که ممکن است باعث مشکلات عملکرد شود.
  • پشته جاوا را تخلیه کنید تا ببینید کدام اشیاء در هر لحظه از حافظه استفاده می کنند. چندین بار تخلیه در یک دوره زمانی طولانی می تواند به شناسایی نشت حافظه کمک کند.
  • تخصیص حافظه را در طول تعامل عادی و شدید کاربر ضبط کنید تا دقیقاً شناسایی کنید که کد شما در یک زمان کوتاه تعداد زیادی اشیاء را تخصیص می دهد یا اشیایی را که لو رفته اند را تخصیص می دهد.

برای کسب اطلاعات در مورد شیوه‌های برنامه‌نویسی که می‌توانند استفاده از حافظه برنامه شما را کاهش دهند، مدیریت حافظه برنامه خود را بخوانید.

نمای کلی حافظه

هنگامی که برای اولین بار Memory Profiler را باز می کنید، جدول زمانی دقیقی از استفاده از حافظه برنامه خود و ابزارهای دسترسی برای جمع آوری زباله، گرفتن یک انبار پشته و ضبط تخصیص حافظه را مشاهده خواهید کرد.

شکل 1. نمایه کننده حافظه

همانطور که در شکل 1 نشان داده شده است، نمای پیش فرض برای Memory Profiler شامل موارد زیر است:

  1. دکمه ای برای اجبار یک رویداد جمع آوری زباله.
  2. دکمه ای برای گرفتن یک توده خالی .

    توجه: دکمه ای برای ضبط تخصیص حافظه تنها زمانی در سمت راست دکمه heap dump ظاهر می شود که به دستگاه دارای Android 7.1 (سطح API 25) یا پایین تر متصل شود.

  3. یک منوی کشویی برای تعیین تعداد دفعات تخصیص حافظه توسط نمایه ساز. انتخاب گزینه مناسب ممکن است به شما در بهبود عملکرد برنامه در حین نمایه سازی کمک کند.
  4. دکمه‌هایی برای بزرگ‌نمایی/کوچ کردن خط زمانی.
  5. دکمه ای برای پرش به جلو به داده های حافظه زنده.
  6. جدول زمانی رویداد که وضعیت‌های فعالیت، رویدادهای ورودی کاربر و رویدادهای چرخش صفحه را نشان می‌دهد.
  7. جدول زمانی استفاده از حافظه که شامل موارد زیر است:
    • نمودار انباشته ای از مقدار حافظه مصرف شده توسط هر دسته حافظه، همانطور که با محور y در سمت چپ و کلید رنگی در بالا نشان داده شده است.
    • یک خط چین نشان دهنده تعداد اشیاء اختصاص داده شده است، همانطور که با محور y در سمت راست نشان داده شده است.
    • یک نماد برای هر رویداد جمع آوری زباله.

با این حال، اگر از دستگاهی استفاده می‌کنید که Android نسخه ۷.۱ یا پایین‌تر دارد، همه داده‌های نمایه‌سازی به‌طور پیش‌فرض قابل مشاهده نیستند. اگر پیامی را مشاهده کردید که می‌گوید «نمایه‌سازی پیشرفته برای فرآیند انتخاب‌شده در دسترس نیست»، باید پروفایل پیشرفته را فعال کنید تا موارد زیر را ببینید:

  • جدول زمانی رویداد
  • تعداد اشیاء اختصاص داده شده
  • رویدادهای جمع آوری زباله

در اندروید 8.0 و بالاتر، نمایه سازی پیشرفته همیشه برای برنامه های قابل اشکال زدایی فعال است.

نحوه شمارش حافظه

اعدادی که در بالای Memory Profiler (شکل 2) مشاهده می کنید، بر اساس تمام صفحات حافظه خصوصی که برنامه شما متعهد شده است، طبق سیستم اندروید است. این تعداد شامل صفحات به اشتراک گذاشته شده با سیستم یا سایر برنامه ها نمی شود.

شکل 2. افسانه شمارش حافظه در بالای Memory Profiler

دسته بندی ها در شمارش حافظه به شرح زیر است:

  • جاوا : حافظه از اشیاء اختصاص داده شده از کد جاوا یا کاتلین.
  • Native : حافظه از اشیاء اختصاص داده شده از کد C یا C++.

    حتی اگر از ++C در برنامه خود استفاده نمی‌کنید، ممکن است برخی از حافظه‌های بومی را در اینجا مشاهده کنید زیرا فریم ورک اندروید از حافظه بومی برای انجام کارهای مختلف از طرف شما استفاده می‌کند، مانند هنگام مدیریت دارایی‌های تصویر و سایر گرافیک‌ها - حتی اگر کد شما نوشته شده در جاوا یا کاتلین است.

  • گرافیک : حافظه ای که برای صف های بافر گرافیکی برای نمایش پیکسل ها روی صفحه نمایش استفاده می شود، از جمله سطوح GL، بافت های GL و غیره. (توجه داشته باشید که این حافظه مشترک با CPU است، نه حافظه اختصاصی GPU.)

  • پشته : حافظه ای که توسط پشته های بومی و جاوا در برنامه شما استفاده می شود. این معمولاً به تعداد رشته هایی که برنامه شما در حال اجرا است مربوط می شود.

  • کد : حافظه ای که برنامه شما برای کد و منابع استفاده می کند، مانند بایت کد dex، کد dex بهینه یا کامپایل شده، کتابخانه های .so، و فونت ها.

  • سایرین : حافظه مورد استفاده برنامه شما که سیستم مطمئن نیست چگونه آن را دسته بندی کند.

  • اختصاص داده شده : تعداد اشیاء جاوا/کوتلین که توسط برنامه شما اختصاص داده شده است. این اشیاء اختصاص داده شده در C یا C++ را به حساب نمی آورد.

    وقتی به دستگاهی با Android نسخه ۷.۱ و پایین‌تر متصل می‌شوید، این تعداد تخصیص تنها زمانی شروع می‌شود که نمایه‌گر حافظه به برنامه در حال اجرا شما متصل شود. بنابراین، اشیایی که قبل از شروع نمایه‌سازی تخصیص داده می‌شوند، حساب نمی‌شوند. با این حال، Android 8.0 و بالاتر شامل یک ابزار نمایه‌سازی روی دستگاه است که همه تخصیص‌ها را ردیابی می‌کند، بنابراین این عدد همیشه نشان‌دهنده تعداد کل اشیاء جاوای برجسته در برنامه شما در Android 8.0 و بالاتر است.

در مقایسه با تعداد حافظه از ابزار قبلی مانیتور اندروید، نمایه‌گر حافظه جدید حافظه شما را متفاوت ضبط می‌کند، بنابراین ممکن است به نظر برسد که استفاده از حافظه شما اکنون بیشتر شده است. Memory Profiler برخی دسته‌های اضافی را نظارت می‌کند که کل را افزایش می‌دهد، اما اگر فقط به حافظه پشته جاوا اهمیت می‌دهید، عدد "Java" باید مشابه مقدار ابزار قبلی باشد. اگرچه احتمالاً شماره جاوا دقیقاً با آنچه در مانیتور اندروید دیدید مطابقت ندارد، شماره جدید تمام صفحات حافظه فیزیکی را که از زمانی که از Zygote جدا شده است به پشته جاوا برنامه شما اختصاص داده شده است. بنابراین این یک نمایش دقیق از میزان حافظه فیزیکی واقعی برنامه شما ارائه می دهد.

مشاهده تخصیص حافظه

تخصیص حافظه به شما نشان می دهد که هر شی جاوا و مرجع JNI در حافظه شما چگونه تخصیص داده شده است. به طور خاص، Memory Profiler می تواند موارد زیر را در مورد تخصیص اشیا به شما نشان دهد:

  • چه نوع اشیایی به آنها اختصاص داده شد و چه مقدار از فضا استفاده می شود.
  • رد پشته هر تخصیص، از جمله در کدام رشته.
  • زمانی که اشیاء جابجا شدند (فقط هنگام استفاده از دستگاهی با Android 8.0 یا بالاتر).

برای ضبط تخصیص جاوا و کاتلین، Record Java/Kotlin allocations را انتخاب کنید، سپس Record را انتخاب کنید. اگر دستگاه دارای Android 8 یا بالاتر باشد، رابط کاربری Memory Profiler به صفحه‌ای جداگانه منتقل می‌شود که ضبط در حال انجام را نشان می‌دهد. می توانید با جدول زمانی کوچک بالای ضبط تعامل داشته باشید (مثلاً برای تغییر محدوده انتخاب). برای تکمیل ضبط، Stop را انتخاب کنید .

تجسم تخصیص جاوا در Memory Profiler

در اندروید 7.1 و پایین‌تر، نمایه‌ساز حافظه از ضبط تخصیص قدیمی استفاده می‌کند که تا زمانی که روی توقف کلیک کنید، ضبط را در خط زمانی نمایش می‌دهد.

پس از انتخاب یک منطقه از خط زمانی (یا هنگامی که یک جلسه ضبط را با دستگاهی که Android نسخه 7.1 یا پایین‌تر دارد، به پایان می‌رسانید)، فهرستی از اشیاء تخصیص‌یافته ظاهر می‌شود که بر اساس نام کلاس گروه‌بندی شده و بر اساس تعداد پشته‌های آنها مرتب شده‌اند.

برای بررسی رکورد تخصیص، مراحل زیر را دنبال کنید:

  1. فهرست را مرور کنید تا اشیایی را بیابید که تعداد انبوهی غیرمعمول زیادی دارند و ممکن است لو رفته باشند. برای کمک به یافتن کلاس های شناخته شده، روی سربرگ ستون نام کلاس کلیک کنید تا بر اساس حروف الفبا مرتب شوند. سپس روی نام کلاس کلیک کنید. پنجره Instance View در سمت راست ظاهر می شود و هر نمونه از آن کلاس را همانطور که در شکل 3 نشان داده شده است نشان می دهد.
    • از طرف دیگر، می‌توانید با کلیک بر روی فیلتر ، اشیاء را به سرعت پیدا کنید ، یا با فشار دادن Control+F (Command+F در Mac) و وارد کردن نام کلاس یا بسته در قسمت جستجو. اگر از منوی کشویی Arrange by callstack را انتخاب کنید، می‌توانید بر اساس نام روش جستجو کنید. اگر می‌خواهید از عبارات منظم استفاده کنید، کادر کنار Regex را علامت بزنید. اگر عبارت جستجوی شما به حروف کوچک و بزرگ حساس است، کادر کنار Match case را علامت بزنید.
  2. در پنجره Instance View ، روی یک نمونه کلیک کنید. زبانه Call Stack در زیر ظاهر می‌شود، که نشان می‌دهد آن نمونه کجا و در کدام رشته تخصیص داده شده است.
  3. در تب Call Stack ، روی هر خطی کلیک راست کرده و گزینه Jump to Source را انتخاب کنید تا آن کد در ویرایشگر باز شود.

شکل 3. جزئیات مربوط به هر شی اختصاص داده شده در نمای نمونه در سمت راست ظاهر می شود

می‌توانید از دو منوی بالای فهرست اشیاء تخصیص‌یافته استفاده کنید تا انتخاب کنید کدام پشته را بررسی کنید و چگونه داده‌ها را سازماندهی کنید.

از منوی سمت چپ، انتخاب کنید کدام پشته را بررسی کنید:

  • پشته پیش فرض : زمانی که هیچ پشته ای توسط سیستم مشخص نشده باشد.
  • تصویر پشته : تصویر بوت سیستم، حاوی کلاس هایی است که در زمان بوت از قبل بارگذاری شده اند. تخصیص ها در اینجا تضمین شده است که هرگز جابجا نمی شوند یا از بین نمی روند.
  • هیپ zygote : پشته کپی در نوشتن که در آن فرآیند برنامه از سیستم اندروید فوک می‌شود.
  • app heap : پشته اصلی که برنامه شما حافظه را به آن اختصاص می دهد.
  • پشته JNI : پشته ای که نشان می دهد منابع رابط بومی جاوا (JNI) کجا تخصیص یافته و منتشر می شوند.

از منوی سمت راست، نحوه ترتیب دادن تخصیص ها را انتخاب کنید:

  • ترتیب بر اساس کلاس : همه تخصیص ها را بر اساس نام کلاس گروه بندی می کند. این پیش فرض است.
  • ترتیب بر اساس بسته : همه تخصیص ها را بر اساس نام بسته گروه بندی می کند.
  • ترتیب بر اساس پشته تماس : همه تخصیص ها را در پشته تماس مربوطه خود گروه بندی می کند.

بهبود عملکرد برنامه در حین نمایه سازی

برای بهبود عملکرد برنامه در حین نمایه سازی، نمایه ساز حافظه به صورت پیش فرض از تخصیص حافظه به صورت دوره ای نمونه برداری می کند. هنگام آزمایش بر روی دستگاه‌هایی که دارای API سطح 26 یا بالاتر هستند، می‌توانید این رفتار را با استفاده از منوی کشویی ردیابی تخصیص تغییر دهید. گزینه های موجود به شرح زیر است:

  • Full : تمام تخصیص های شی در حافظه را ضبط می کند. این رفتار پیش‌فرض در اندروید استودیو 3.2 و نسخه‌های قبلی است. اگر برنامه‌ای دارید که اشیاء زیادی را به خود اختصاص می‌دهد، ممکن است در حین پروفایل کردن، کاهش سرعت قابل مشاهده را در برنامه خود مشاهده کنید.
  • Sampled : از تخصیص اشیا در حافظه در فواصل زمانی منظم نمونه برداری می کند. این گزینه پیش‌فرض است و تأثیر کمتری بر عملکرد برنامه در حین نمایه‌سازی دارد. برنامه‌هایی که اشیاء زیادی را در یک بازه زمانی کوتاه تخصیص می‌دهند، ممکن است همچنان کندی قابل مشاهده از خود نشان دهند.
  • خاموش : ردیابی تخصیص حافظه برنامه شما را متوقف می کند.

مراجع جهانی JNI را مشاهده کنید

رابط بومی جاوا (JNI) چارچوبی است که به کد جاوا و کد بومی اجازه می دهد تا یکدیگر را فراخوانی کنند.

ارجاعات JNI به صورت دستی توسط کد اصلی مدیریت می شوند، بنابراین ممکن است اشیاء جاوا که توسط کد بومی استفاده می شوند برای مدت طولانی زنده نگه داشته شوند. اگر یک مرجع JNI بدون حذف صریح حذف شود، ممکن است برخی از اشیاء روی پشته جاوا غیرقابل دسترس شوند. همچنین، ممکن است محدودیت مرجع جهانی JNI تمام شود.

برای عیب یابی چنین مشکلاتی، از نمای پشته JNI در Memory Profiler استفاده کنید تا تمام مراجع جهانی JNI را مرور کنید و آنها را بر اساس انواع جاوا و پشته های تماس بومی فیلتر کنید. با این اطلاعات، می توانید زمان و مکان ایجاد و حذف مراجع جهانی JNI را پیدا کنید.

در حالی که برنامه شما در حال اجرا است، بخشی از جدول زمانی را که می خواهید بررسی کنید انتخاب کنید و JNI heap را از منوی کشویی بالای لیست کلاس انتخاب کنید. سپس می توانید مانند شکل 4 اشیاء موجود در پشته را بررسی کنید و روی اشیاء در تب Allocation Call Stack دوبار کلیک کنید تا ببینید منابع JNI در کد شما در کجا تخصیص داده شده و آزاد می شوند، همانطور که در شکل 4 نشان داده شده است.

شکل 4. مشاهده مراجع جهانی JNI

برای بررسی تخصیص حافظه برای کد JNI برنامه خود، باید برنامه خود را روی دستگاهی با Android نسخه 8.0 یا بالاتر اجرا کنید.

برای اطلاعات بیشتر در مورد JNI، به نکات JNI مراجعه کنید.

نمایه کننده حافظه بومی

نمایه‌ساز حافظه اندروید استودیو شامل یک نمایه حافظه بومی برای برنامه‌هایی است که بر روی دستگاه‌های فیزیکی و مجازی دارای Android 10 و بالاتر نصب شده‌اند.

Native Memory Profiler تخصیص/تخصیص اشیا را در کد بومی برای یک دوره زمانی خاص دنبال می کند و اطلاعات زیر را ارائه می دهد:

  • تخصیص ها: تعداد اشیایی که از طریق malloc() یا عملگر new در طول دوره زمانی انتخاب شده تخصیص داده شده اند.
  • Deallocations: تعداد اشیایی که از طریق free() یا عملگر delete در طول بازه زمانی انتخاب شده توزیع شده اند.
  • اندازه تخصیص ها: اندازه جمع آوری شده در بایت همه تخصیص ها در طول دوره زمانی انتخاب شده.
  • Deallocations Size: اندازه جمع آوری شده در بایت از تمام حافظه آزاد شده در طول دوره زمانی انتخاب شده.
  • تعداد کل: مقدار در ستون تخصیص منهای مقدار در ستون Deallocations .
  • Remaining Size: مقدار موجود در ستون Allocations Size منهای مقدار در ستون Deallocations Size .

نمایه کننده حافظه بومی

برای ضبط تخصیص‌های بومی در دستگاه‌های دارای Android 10 و بالاتر، ضبط تخصیص‌های بومی و سپس ضبط را انتخاب کنید. ضبط تا زمانی که روی Stop کلیک کنید ادامه می یابد ، پس از آن رابط کاربری Memory Profiler به یک صفحه جداگانه انتقال می یابد که ضبط بومی را نمایش می دهد.

دکمه تخصیص بومی ضبط

در اندروید 9 و پایین تر، گزینه Record native allocations در دسترس نیست.

به طور پیش فرض، Native Memory Profiler از اندازه نمونه 32 بایت استفاده می کند: هر بار که 32 بایت حافظه اختصاص داده می شود، یک عکس فوری از حافظه گرفته می شود. اندازه نمونه کوچکتر منجر به عکس های فوری بیشتر می شود و داده های دقیق تری در مورد استفاده از حافظه به دست می دهد. حجم نمونه بزرگتر داده های دقیق کمتری به دست می دهد، اما منابع کمتری را در سیستم شما مصرف می کند و عملکرد را در حین ضبط بهبود می بخشد.

برای تغییر اندازه نمونه Native Memory Profiler:

  1. Run > Edit Configurations را انتخاب کنید.
  2. ماژول برنامه خود را در قسمت سمت چپ انتخاب کنید.
  3. روی برگه Profilling کلیک کنید و اندازه نمونه را در فیلدی با عنوان Native memory interval sampling (بایت) وارد کنید.
  4. برنامه خود را دوباره بسازید و اجرا کنید.

یک توده زباله را ضبط کنید

یک heap dump نشان می‌دهد که کدام اشیاء در برنامه شما از حافظه استفاده می‌کنند در زمانی که شما heap dump را می‌گیرید. به خصوص پس از یک جلسه طولانی کاربر، یک heap dump می تواند با نشان دادن اشیایی که هنوز در حافظه هستند و فکر می کنید دیگر نباید وجود داشته باشند، به شناسایی نشت حافظه کمک کند.

پس از گرفتن یک heap dump، می توانید موارد زیر را مشاهده کنید:

  • برنامه شما چه نوع اشیایی را اختصاص داده است و چه تعداد از هر کدام.
  • هر شی از چه مقدار حافظه استفاده می کند.
  • جایی که ارجاعات به هر شی در کد شما نگهداری می شود.
  • پشته تماس برای جایی که یک شی تخصیص داده شده است. (درحال‌حاضر پشته‌های تماس با Heap Dump فقط با Android نسخه 7.1 و پایین‌تر در هنگام ضبط تخصیص‌ها، در دسترس هستند.)

برای گرفتن عکس پشته، روی Capture heap dump کلیک کنید، سپس ضبط را انتخاب کنید. در حین تخلیه پشته، مقدار حافظه جاوا ممکن است به طور موقت افزایش یابد. این طبیعی است زیرا heap dump در همان فرآیند برنامه شما رخ می دهد و برای جمع آوری داده ها به مقداری حافظه نیاز دارد.

پس از اینکه پروفیل‌گر ضبط پشته را تمام کرد، رابط کاربری Memory Profiler به صفحه جداگانه‌ای منتقل می‌شود که حفره پشته را نشان می‌دهد.

شکل 5. مشاهده توده های زباله.

اگر می‌خواهید درباره زمان ایجاد dump دقیق‌تر باشید، می‌توانید با فراخوانی dumpHprofData() یک heap dump در نقطه بحرانی کد برنامه خود ایجاد کنید.

در لیست کلاس ها می توانید اطلاعات زیر را مشاهده کنید:

  • تخصیص ها : تعداد تخصیص ها در پشته.
  • Native Size : کل مقدار حافظه بومی مورد استفاده این نوع شی (بر حسب بایت). این ستون فقط برای اندروید 7.0 و بالاتر قابل مشاهده است.

    در اینجا برای برخی از اشیاء تخصیص داده شده در جاوا حافظه خواهید دید زیرا اندروید برای برخی از کلاس های فریمورک از حافظه داخلی استفاده می کند، مانند Bitmap .

  • اندازه کم عمق : مقدار کل حافظه جاوای استفاده شده توسط این نوع شی (بر حسب بایت).

  • Retained Size : اندازه کل حافظه ای که به دلیل تمام نمونه های این کلاس (بر حسب بایت) حفظ می شود.

می‌توانید از دو منوی بالای فهرست اشیاء تخصیص‌یافته استفاده کنید تا انتخاب کنید کدام حفره‌های خالی را بررسی کنید و چگونه داده‌ها را سازماندهی کنید.

از منوی سمت چپ، انتخاب کنید کدام پشته را بررسی کنید:

  • پشته پیش فرض : زمانی که هیچ پشته ای توسط سیستم مشخص نشده باشد.
  • app heap : پشته اصلی که برنامه شما حافظه را به آن اختصاص می دهد.
  • تصویر پشته : تصویر بوت سیستم، حاوی کلاس هایی است که در زمان بوت از قبل بارگذاری شده اند. تخصیص ها در اینجا تضمین شده است که هرگز جابجا نمی شوند یا از بین نمی روند.
  • هیپ zygote : پشته کپی در نوشتن که در آن فرآیند برنامه از سیستم اندروید فوک می‌شود.

از منوی سمت راست، نحوه ترتیب دادن تخصیص ها را انتخاب کنید:

  • ترتیب بر اساس کلاس : همه تخصیص ها را بر اساس نام کلاس گروه بندی می کند. این پیش فرض است.
  • ترتیب بر اساس بسته : همه تخصیص ها را بر اساس نام بسته گروه بندی می کند.
  • ترتیب بر اساس پشته تماس : همه تخصیص ها را در پشته تماس مربوطه خود گروه بندی می کند. این گزینه فقط در صورتی کار می‌کند که هنگام ضبط تخصیص‌ها، از heap dump عکس بگیرید. با این حال، احتمالاً اشیایی در پشته وجود دارد که قبل از شروع ضبط به شما اختصاص داده شده است، بنابراین آن تخصیص ها ابتدا ظاهر می شوند و به سادگی با نام کلاس فهرست می شوند.

لیست به طور پیش فرض بر اساس ستون Retained Size مرتب شده است. برای مرتب کردن بر اساس مقادیر در یک ستون دیگر، روی عنوان ستون کلیک کنید.

روی نام کلاس کلیک کنید تا پنجره Instance View در سمت راست (نشان داده شده در شکل 6) باز شود. هر نمونه فهرست شده شامل موارد زیر است:

  • عمق : کوتاه ترین تعداد پرش از هر ریشه GC تا نمونه انتخاب شده.
  • Native Size : اندازه این نمونه در حافظه اصلی. این ستون فقط برای اندروید 7.0 و بالاتر قابل مشاهده است.
  • Shallow Size : اندازه این نمونه در حافظه جاوا.
  • Retained Size : اندازه حافظه ای که این نمونه بر آن غالب است (طبق درخت غالب ).

شکل 6. مدت زمان مورد نیاز برای گرفتن حفره پشته در جدول زمانی نشان داده شده است

برای بررسی پشته خود، این مراحل را دنبال کنید:

  1. فهرست را مرور کنید تا اشیایی را بیابید که تعداد انبوهی غیرمعمول زیادی دارند و ممکن است لو رفته باشند. برای کمک به یافتن کلاس های شناخته شده، روی سربرگ ستون نام کلاس کلیک کنید تا بر اساس حروف الفبا مرتب شوند. سپس روی نام کلاس کلیک کنید. پنجره Instance View در سمت راست ظاهر می شود و هر نمونه از آن کلاس را همانطور که در شکل 6 نشان داده شده است نشان می دهد.
    • از طرف دیگر، می‌توانید با کلیک بر روی فیلتر ، اشیاء را به سرعت پیدا کنید ، یا با فشار دادن Control+F (Command+F در Mac) و وارد کردن نام کلاس یا بسته در قسمت جستجو. اگر از منوی کشویی Arrange by callstack را انتخاب کنید، می‌توانید بر اساس نام روش جستجو کنید. اگر می‌خواهید از عبارات منظم استفاده کنید، کادر کنار Regex را علامت بزنید. اگر عبارت جستجوی شما به حروف کوچک و بزرگ حساس است، کادر کنار Match case را علامت بزنید.
  2. در پنجره Instance View ، روی یک نمونه کلیک کنید. تب References در زیر ظاهر می شود و هر ارجاع به آن شی را نشان می دهد.

    یا روی فلش کنار نام نمونه کلیک کنید تا همه فیلدهای آن را مشاهده کنید و سپس روی نام فیلد کلیک کنید تا همه مراجع آن را مشاهده کنید. اگر می خواهید جزئیات نمونه یک فیلد را مشاهده کنید، روی فیلد کلیک راست کرده و Go to Instance را انتخاب کنید.

  3. در برگه References ، اگر مرجعی را شناسایی کردید که ممکن است حافظه نشت کند، روی آن کلیک راست کرده و Go to Instance را انتخاب کنید. این نمونه متناظر را از heap dump انتخاب می‌کند و داده‌های نمونه خودش را به شما نشان می‌دهد.

در heap dump خود، به دنبال نشت حافظه ناشی از یکی از موارد زیر باشید:

  • ارجاع طولانی مدت به Activity ، Context ، View ، Drawable و سایر اشیایی که ممکن است ارجاعی به Activity یا Context داشته باشند.
  • کلاس‌های داخلی غیراستاتیک، مانند Runnable ، که می‌توانند نمونه‌ای از Activity را نگه دارند.
  • حافظه های پنهانی که اشیاء را بیش از حد لازم نگه می دارند.

یک heap dump را به عنوان یک فایل HPROF ذخیره کنید

پس از ثبت یک پشته، داده‌ها در نمایه‌گر حافظه فقط زمانی که نمایه‌ساز در حال اجرا است قابل مشاهده است. وقتی از جلسه پروفایل خارج می‌شوید، heap dump را از دست می‌دهید. بنابراین، اگر می‌خواهید آن را برای بررسی بعداً ذخیره کنید، heap dump را به یک فایل HPROF صادر کنید. در Android Studio نسخه 3.1 و پایین‌تر، Export capture to file دکمه در سمت چپ نوار ابزار زیر خط زمانی قرار دارد. در Android Studio نسخه 3.2 و بالاتر، یک دکمه Export Heap Dump در سمت راست هر ورودی Heap Dump در قسمت Sessions وجود دارد. در گفتگوی Export As که ظاهر می شود، فایل را با پسوند .hprof file-name ذخیره کنید.

برای استفاده از یک آنالایزر مختلف HPROF مانند jhat ، باید فایل HPROF را از فرمت Android به فرمت Java SE HPROF تبدیل کنید. می توانید این کار را با ابزار hprof-conv ارائه شده در فهرست راهنمای android_sdk /platform-tools/ انجام دهید. دستور hprof-conv را با دو آرگومان اجرا کنید: فایل HPROF اصلی و محل نوشتن فایل HPROF تبدیل شده. به عنوان مثال:

hprof-conv heap-original.hprof heap-converted.hprof

فایل heap dump را وارد کنید

برای وارد کردن یک فایل HPROF ( .hprof )، روی شروع یک جلسه پروفایل جدید کلیک کنید در قسمت Sessions ، Load from file را انتخاب کنید و فایل را از مرورگر فایل انتخاب کنید.

همچنین می توانید یک فایل HPROF را با کشیدن آن از مرورگر فایل به پنجره ویرایشگر وارد کنید.

تشخیص نشت در Memory Profiler

هنگام تجزیه و تحلیل heap dump در Memory Profiler، می‌توانید داده‌های نمایه‌ای را فیلتر کنید که Android Studio فکر می‌کند ممکن است نشان دهنده نشت حافظه برای نمونه‌های Activity و Fragment در برنامه شما باشد.

انواع داده هایی که فیلتر نشان می دهد شامل موارد زیر است:

  • نمونه‌های Activity که از بین رفته‌اند اما هنوز به آنها ارجاع داده می‌شود.
  • نمونه های Fragment که FragmentManager معتبری ندارند اما همچنان به آنها ارجاع داده می شود.

در شرایط خاص، مانند موارد زیر، فیلتر ممکن است مثبت کاذب باشد:

  • یک Fragment ایجاد شده است اما هنوز استفاده نشده است.
  • یک Fragment در حافظه پنهان ذخیره می شود، اما نه به عنوان بخشی از یک FragmentTransaction .

برای استفاده از این ویژگی، ابتدا یک فایل heap dump بگیرید یا یک فایل heap dump را به Android Studio وارد کنید . همانطور که در شکل 7 نشان داده شده است، برای نمایش قطعات و فعالیت هایی که ممکن است حافظه را نشت کند، کادر بررسی Activity/Fragment Leaks را در قسمت heap dump panel Memory Profiler انتخاب کنید.

نمایه: تشخیص نشت حافظه

شکل 7. فیلتر کردن یک heap dump برای نشت حافظه.

تکنیک هایی برای نمایه سازی حافظه شما

هنگام استفاده از Memory Profiler، باید روی کد برنامه خود تاکید کنید و سعی کنید به اجبار نشت حافظه را انجام دهید. یکی از راه‌های برانگیختن نشت حافظه در برنامه‌تان این است که قبل از بررسی پشته، اجازه دهید مدتی اجرا شود. نشت ممکن است به بالای تخصیص در پشته برسد. با این حال، هر چه نشتی کوچکتر باشد، برای دیدن برنامه به مدت زمان بیشتری نیاز دارید.

همچنین می توانید نشت حافظه را به یکی از روش های زیر راه اندازی کنید:

  • دستگاه را از حالت عمودی به منظره بچرخانید و در حالت های مختلف فعالیت چندین بار به عقب برگردید. چرخاندن دستگاه اغلب می‌تواند باعث لو رفتن یک شیء Activity ، Context یا View برنامه شود، زیرا سیستم Activity را دوباره ایجاد می‌کند و اگر برنامه شما به یکی از آن اشیاء در جای دیگری ارجاع داشته باشد، سیستم نمی‌تواند آن را زباله جمع‌آوری کند.
  • هنگامی که در حالت‌های مختلف فعالیت هستید، بین برنامه خود و برنامه دیگری جابجا شوید (به صفحه اصلی بروید، سپس به برنامه خود بازگردید).

نکته: همچنین می توانید مراحل بالا را با استفاده از چارچوب تست monkeyrunner انجام دهید.