Официальный сайт движения «Москва без Лужкова!»
Главная Новости Москвы Наши новости Популярное
  • Новости
  • Новости
  • ВХОД В ЛИЧНЫЙ КАБИНЕТ
    логин
    пароль
       
    Новости

    Поради щодо оптимізації використання пам'яті додатками Android *

    1. Вступ Виділення і звільнення пам'яті в Android * завжди досягалися високою ціною. Китайське прислів'я...
    2. Як поліпшити використання пам'яті
    3. Як уникнути витоків пам'яті
    4. Як проаналізувати використання пам'яті
    5. висновок
    6. Довідкові матеріали
    7. про автора

    Вступ

    Виділення і звільнення пам'яті в Android * завжди досягалися високою ціною. Китайське прислів'я говорить: «Після бідності легко звикнути до розкоші, але після розкоші важко звикнути до бідності». Ця фраза цілком застосовна і до використання пам'яті додатками.

    Уявімо собі найгірший можливий сценарій: йде компіляція програми з мільйонами рядків коду, і раптово відбувається збій через брак пам'яті (ООМ). Ви починаєте налагоджувати додаток і аналізувати файл hprof. Якщо пощастить, то ви зможете знайти причину збою і усунути проблему нестачі пам'яті. Але іноді везіння обходить вас стороною, ви виявляєте, що безліч дрібних змінних і тимчасових об'єктів виділяє пам'ять таким чином, що не існує простого способу виправити цю проблему. Це означає, що доведеться перебудовувати код, що завжди пов'язано з потенційним ризиком, і лише заради того, щоб заощадити кілька кілобайт, а іноді і кілька байт пам'яті.

    У цій статті описується управління пам'яттю в Android і пояснюються різні аспекти і особливості системи управління пам'яттю. Крім того, розглядаються такі питання, як більш ефективне управління пам'яттю, виявлення і усунення витоків пам'яті, аналіз використання пам'яті.

    Управління пам'яттю в Android

    В Android використовуються пейджинг і mmap замість простору підкачки. Це означає, що пам'ять, порушену вашим додатком, неможливо використовувати до вивільнення всіх посилань.

    У віртуальній машині Dalvik * розмір купи для процесів додатків обмежений. Додатки починають роботу з 2 МБ, а максимальний розмір виділення, званий largeHeap, становить до 36 МБ (в залежності від конфігурації конкретного пристрою). Приклади застосування з великою купою: редактори фото і відео, камера, галерея, домашній екран.

    Фонові процеси додатків в Android зберігаються в кеші LRU (кеш найбільш давно використаних елементів). Коли в системі закінчується пам'ять, система завершує процеси згідно зі стратегією LRU, але при цьому враховує, яка програма займає найбільше пам'яті. В даний час гранична кількість фонових процесів дорівнює 20 (в залежності від конфігурації конкретного пристрою). Якщо потрібно, щоб додаток довше залишалося в фоновому режимі, зніміть позначки непотрібної пам'яті перед перемиканням в фоновий режим, тоді Android з меншою ймовірністю видасть повідомлення про помилку або навіть завершить роботу цього додатка.

    Як поліпшити використання пам'яті

    Android is a worldwide mobile platform and millions of Android developers are dedicated to building stable and scalable applications. Here is a list of tips and best practices for improving memory usage in Android applications:

    1. Будьте обережні при використанні «абстракцій». Втім, з точки зору архітектури абстракція може допомогти в досягненні більш високої гнучкості. У мобільних рішеннях у абстракції може бути побічний ефект, який полягає у виконанні додаткового коду, через що витрачається більше ресурсів ЦП і пам'яті. Використовувати абстракцію слід лише в тому випадку, якщо вона дає вашому додатку відчутну перевагу.
    2. Не використовуйте enum. У порівнянні зі звичайними статичними константами при використанні enum виділяться вдвічі більше пам'яті.
    3. Спробуйте використовувати оптимізовані контейнери SparseArray, SparseBooleanArray і LongSparseArray замість HashMap. HashMap виділяє об'єкт входження при кожному зіставленні. Це дуже неефективно з точки зору пам'яті і з точки зору продуктивності, оскільки супроводжується безліччю операцій автоматичної упаковки і розпаковування. Контейнери на зразок SparseArray зіставляють ключі з простими масивами. Але пам'ятайте, що такі оптимізовані контейнери непридатні для великої кількості елементів; при виконанні дій додавання, видалення та пошуку вони повільніше, ніж Hashmap, якщо набір даних містить кілька тисяч записів.
    4. Не створюйте непотрібні об'єкти. Чи не виділяйте пам'ять для короткострокових тимчасових об'єктів, якщо можна обійтися без цього, а чим менше створено об'єктів, тим рідше відбувається прибирання сміття.
    5. Перевіряйте доступність купи вашого застосування. Викликайте ActivityManager :: getMemoryClass (), щоб запросити, який обсяг купи (в МБ) доступний для додатка. При спробі виділити більше пам'яті, ніж доступно, виникне виключення OutofMemory. Якщо додаток оголошує largeHeap в AndroidManifest.xml, то можна викликати ActivityManager :: getLargeMemoryClass () для запиту передбачуваного розміру великої купи.
    6. Скоординує роботу з системою за допомогою зворотного виклику onTrimMemory (). Використовуйте ComponentCallbacks2 :: onTrimMemory (int) в Activity / Service / ContentProvider для поступового вивільнення пам'яті згідно з останніми обмеженням системи. Завдяки onTrimMemory (int) підвищується загальна швидкість відгуку системи, але процеси довше підтримуються в активному стані.
      Коли виникає подія TRIM_MEMORY_UI_HIDDEN, це означає, що весь призначений для користувача інтерфейс вашої програми був прихований і потрібно вивільнити ресурси для користувача інтерфейсу. Коли додаток працює в режимі переднього плану, можуть з'явитися повідомлення TRIM_MEMORY_RUNNING [MODERATE / LOW / CRITICAL], а в фоновому режимі - TRIM_MEMORY_ [BACKGROUND / MODERATE / COMPLETE]. Можна звільнити пам'ять від другорядних ресурсів на основі стратегії вивільнення пам'яті при її нестачі.

    7. Використовуйте служби з обережністю. Якщо служба потрібна для виконання завдання у фоновому режимі, підтримуйте її в запущеному стані, тільки якщо вона фактично виконує завдання. Спробуйте скоротити час роботи служби за допомогою IntentService, оскільки в цьому випадку служба закінчить роботу після завершення обробки цілі. Використовувати служби слід з обережністю: ніколи не залишайте запущену службу, якщо вона не потрібна в даний момент. У найгіршому випадку знизиться продуктивність всієї системи, користувачі спробують визначити причину цього, знайдуть ваш додаток і видалять його (якщо це можливо).
      Якщо ж ви створюєте додаток, яке повинно бути запущено протягом тривалого періоду часу, наприклад, службу музичного програвача, його слід розділити на два процеси: один для призначеного для користувача інтерфейсу, а інший для фонової служби. Для цього потрібно задати властивість служби android: process в файлі AndroidManifest.xml. Ресурси в процесі призначеного для користувача інтерфейсу можна вивільняти після приховування додатки, а фонова служба відтворення продовжить працювати. Пам'ятайте, що процес фонової служби ні в якому разі не повинен взаємодіяти з призначеним для користувача інтерфейсом. В іншому випадку обсяг споживаної пам'яті може вирости вдвічі або втричі
    8. Використовуйте зовнішні бібліотеки з обережністю. Найчастіше зовнішні бібліотеки створюються для немобільних пристроїв, тому в Android вони можуть бути неефективні. Беручи рішення про використання тієї чи іншої зовнішньої бібліотеки, обов'язково врахуйте трудовитрати, необхідні для перенесення цієї бібліотеки на мобільну платформу і для її оптимізації. Якщо в якій-небудь бібліотеці використовується лише одна-дві функції з тисяч доступних, то краще написати код цих функцій самостійно.
    9. Використовуйте растрові малюнки правильного вирішення. Завантажуйте растрові малюнки потрібного дозволу або зменшуйте дозвіл, якщо у вихідних растрових малюнків воно занадто велике.
    10. Використовуйте Proguard * і zipalign. Засіб Proguard видаляє невикористаний код і маскує класи, методи і поля. При цьому код стає більш компактним, знижується кількість необхідних розподіляються сторінок оперативної пам'яті. Засіб zipalign перебудовує APK-файл. Якщо засіб zipalign не запущена, потрібно більше пам'яті, оскільки з APK неможливо розподіляти файли ресурсів.

    Як уникнути витоків пам'яті

    Акуратний підхід до використання пам'яті і дотримання перерахованих рад поліпшать роботу вашого застосування. Всі переваги будуть втрачені в разі витоку пам'яті. Ось деякі поширені причини витоків пам'яті, про які слід знати розробникам.

    1. Закривайте курсор після запиту бази даних. Якщо потрібно, щоб курсор був відкритий протягом тривалого часу, користуйтеся їм з обережністю і закривайте його відразу ж після завершення завдання бази даних.
    2. Не забудьте викликати unregisterReceiver () після виклику registerReceiver ().
    3. Уникайте витоку контексту. Якщо оголосити статичну змінну Drawable в Activity, а потім викликати view.setBackground (drawable) в onCreate (), то після повороту екрану буде створений новий екземпляр Activity, а скасувати виділення пам'яті, як і раніше примірнику Activity буде неможливо, оскільки уявлення задано як зворотний виклик і уявлення посилається на Activity (Context). Витік в екземплярі Activity означає витік значного обсягу пам'яті з високою ймовірністю виникнення помилки «Недостатньо пам'яті».
      Уникнути такого витоку можна двома способами:
      • Не зберігайте довгострокові посилання на context-activity. Життєвий цикл посилання на дію повинен бути таким же, як у самого дії.
      • Спробуйте використовувати context-application замість context-activity.
    4. Уникайте нестатичних внутрішніх класів в Activity. В Java нестатичні анонімні класи містять неявну посилання на їх зовнішній клас. При недбалості збереження цієї посилання може спричинити утримання дії в пам'яті, тоді як в іншому випадку його обробив би збирач сміття. Тому використовуйте статичні внутрішні класи і слабкі посилання на які містяться всередині дії.
    5. Будьте обережні при роботі з потоками. Потоки в Java знаходяться поза збірки сміття. Іншими словами, віртуальна машина Dalvik (DVM) зберігає жорсткі посилання на всі активні потоки в системі виконання, тому всі потоки, що залишилися запущеними, не потрапляють під дію збірки сміття. Потоки в Java зберігаються в пам'яті до тих пір, поки або вони не будуть закриті явно, або весь процес не буде завершений системою Android. У середовищі додатків Android підтримується безліч класів, призначених для підвищення зручності фонової роботи з потоками:
      • Використовуйте Loader замість потоку для виконання короткострокових асинхронних фонових запитів разом з життєвим циклом Activity.
      • Використовуйте Service і передавайте результати в Activity за допомогою BroadcastReceiver.
      • Використовуйте AsyncTask для короткострокових операцій.

    Як проаналізувати використання пам'яті

    Для отримання додаткових відомостей про статистику використання пам'яті в інтерактивному і автономному режимах можна переглянути основний журнал Android за допомогою команди logcat в Android Debug Bridge (ADB), інформацію дампа пам'яті для певного імені пакета або за допомогою інших інструментів, таких як Dalvik Debug Monitor Server ( DDMS) і Memory Analyzer Tool (MAT). Ось короткий опис аналізу використання пам'яті вашим додатком.

    1. Перегляньте повідомлення журналу збірки сміття (GC) для віртуальної машини Dalvik згідно наступних прикладів і визначень:

      Перегляньте повідомлення журналу збірки сміття (GC) для віртуальної машини Dalvik згідно наступних прикладів і визначень:

      • Причина збирача сміття. Що запустило збірку сміття і якого типу ця збірка? Причини можуть бути наступними.
        • GC_CONCURRENT: одночасна прибирання сміття, що вивільняє пам'ять у міру заповнення купи.
        • GC_FOR_ALLOC: прибирання сміття, яка запускається через те, що додаток спробувало виділити пам'ять при вже повною купі, тому системі довелося зупинити додаток і повернути пам'ять.
        • GC_HPROF_DUMP_HEAP: прибирання сміття, що виникає при створенні файлу HPROF для аналізу купи.
        • GC_EXPLICIT: запущена явно прибирання сміття, наприклад, виклику gc () (чого слід уникати; потрібно покладатися на те, що збирач сміття сам запуститься в потрібний момент).
      • Звільнений об'єм: обсяг пам'яті, звільнений після цієї збірки сміття.
      • Статистика купи: відсоток вільної пам'яті і (кількість діючих об'єктів / загальний розмір купи).
      • Статистика зовнішньої пам'яті: зовнішня виділена пам'ять на рівні API 10 і нижче (обсяг виділеної пам'яті / межа, після досягнення якого почнеться складання сміття).
      • Час припинення: у більших куп час призупинення буде більше. При одночасній припинення можна побачити дві припинення: одна на початку збірки, а інша ближче до закінчення.

      Чим більше журнал збирача сміття, тим більше операцій виділення і скасування виділення пам'яті відбулося в вашому додатку. Це, в свою чергу, означає зниження зручності користувачів.

    2. Використовуйте DDMS для перегляду оновлень купи і відстеження виділення пам'яті.
      Зручно перевіряти виділення купи в реальному часі для певного процесу за допомогою DDMS. Спробуйте попрацювати з додатком і стежте за оновленням виділення купи на вкладці Heap. Це допоможе визначити, які дії використовують занадто багато пам'яті. На вкладці Allocation Tracker відображаються всі недавні виділення пам'яті із зазначенням типу об'єктів, потоку, класу, файлу і рядки. Додаткові відомості про використання DDMS для аналізу купи см. В розділі довідкових матеріалів в кінці цієї статті. На наступному скріншоті показана програма DDMS з поточними процесами і статистикою купи пам'яті для певного процесу.

    3. Перегляд загального виділення пам'яті.
      За допомогою команди adb - adb shell dumpsys meminfo <Имя_Пакета> - можна переглянути всю поточну виділену пам'ять додатки (в КБ).

      Як правило, слід звертати увагу тільки на стовпці Pss Total і Private Dirty. У стовпці Pss Total включено виділення всіх об'єктів Zygote (з установкою вагового коефіцієнта згідно їх спільному використанню процесами відповідно до визначення PSS вище). У стовпці Private Dirty - обсяг фактичної оперативної пам'яті, наданої купі додатки, виділених областей і всіх сторінок Zygote, зміненим з моменту відгалуження процесу додатки з об'єкта Zygote.
      Крім того, в стовпці ViewRootImpl відображається кількість кореневих уявлень, що діють у вашому процесі. Кожне кореневе уявлення пов'язане з вікном, тому це допоможе виявити витоку пам'яті, пов'язані з діалоговими або іншими вікнами. На вкладках AppContexts і Activities відображається кількість об'єктів Context і Activity додатки, які використовуються в вашому процесі. Це може стати в нагоді для виявлення витоків об'єктів Activity, до яких неможливо застосувати збірку сміття через наявність в них статичних посилань, що буває досить часто. З такими об'єктами часто пов'язано безліч інших ресурсів, і так можна зручно відстежувати великі витоку пам'яті.

    4. Збережіть дамп купи і проаналізуйте його в програмі Eclipse * Memory Analyzer Tool (MAT).
      Записати дамп купи можна безпосередньо за допомогою DDMS, а для більш точних результатів можна викликати Debug :: dumpHprofData () в коді програми. Потім потрібно застосувати програму hprof-conv для отримання перетвореного файлу HPROF. На наступному скріншоті показаний результат аналізу пам'яті в МАТ.

    висновок

    Для створення додатків, ефективно працюють з оперативною пам'яттю, розробникам для Android потрібно базове розуміння принципів управління пам'яттю в Android. Розробникам слід застосовувати методики ефективного використання пам'яті і засоби аналізу, дотримуючись порад, перерахованих в цій статті. Краще з самого початку створити стабільне масштабується додаток, ніж застосовувати виправлення на етапі реалізації.

    Довідкові матеріали

    1. http://developer.android.com/training/articles/memory.html
    2. https://developer.android.com/tools/debugging/debugging-memory.html
    3. http://developer.android.com/training/articles/perf-tips.html
    4. http://android-developers.blogspot.co.uk/2009/01/avoiding-memory-leaks.html
    5. http://developer.android.com/tools/debugging/ddms.html
    6. http://www.curious-creature.com/2008/12/18/avoid-memory-leaks-on-android/comment-page-1/
    7. https://eclipse.org/mat/

    про автора

    Бін Чжу (Bin Zhu) - інженер по розробці додатків в команді Intel® Atom ™ Processor Mobile Enabling Team в підрозділі Developer Relations Division відділу Software and Solutions Group (SSG). Він відповідає за підтримку додатків Android на процесорах Intel Atom, а також займається технологіями мультимедіа на платформах Android x86.

    Що запустило збірку сміття і якого типу ця збірка?

     

    Найди свой район!

    Восточный

    Западный

    Зеленоградский

    Северный

    Северо-Восточный

    Северо-Западный

    Центральный

    Юго-Восточный

    Юго-Западный

    Южный

    Поиск:      


     
    Rambler's Top100
    © 2007 Движение «Москва без Лужкова!»