Який максимальний об'єм оперативної пам’яті може використовувати додаток?


145

Мені дуже цікаво це питання щодо управління пам'яттю операційної системи Android, тому сподіваюся на досить детальну відповідь на цю тему.

Що я хотів би знати:

  • Який максимальний об'єм пам'ятімегабайтах / у відсотках від загальної оперативної пам’яті), яким може користуватися програма Android (тобто не системний додаток)?
  • Чи є різниці між версіями Android ?
  • Чи є якісь відмінності щодо виробника пристрою?

І найголовніше:

  • Що вважається / від чого це залежить, якщо мова йде про систему, яка визначає, скільки оперативної пам’яті додаток може використовувати під час виконання (якщо вважати, що максимум пам’яті на додаток не є статичним числом)?

Що я чув досі (до 2013 року):

  • Ранні пристрої Android мали обмеження на 16 МБ
  • Пізніше цей ковпак збільшився до 24 Мб або 32 МБ

Що мене дуже цікавить:

Обидва ці межі дуже низькі.

Нещодавно я завантажив диспетчер завдань Android, щоб перевірити оперативну пам’ять своїх пристроїв. Що я помітив, це те, що є додатки, які використовують близько 40-50 мегабайт оперативної пам’яті, що набагато більше, ніж згадане максимальне використання оперативної пам’яті, скажімо, 32 Мб. Тож як Android визначає, скільки оперативної пам’яті може використовувати додаток? Як можливо, що додатки перевищують цю межу?

Крім того, я помітив, що деякі програми моєї аварії (вбиті системою?) З OutOfMemoryException при використанні близько 30-40 мегабайт. З іншого боку, у мене на телефоні працюють програми на 100 Мб і більше через деякий час (можливо, через витоки пам'яті), які не збиваються і не забиваються. Тож, очевидно, це також залежить від самого додатка, коли мова йде про те, наскільки оперативної пам'яті можна заощадити. Як це можливо? (Я проводив свої тести на HTC One S із 768 МБ оперативної пам’яті)

Відмова: Я жодним чином не пов'язаний з додатком Android Task Manager.

Відповіді:


119

Який максимальний об'єм пам'яті (у мегабайтах / у відсотках від загальної оперативної пам’яті), яким може користуватися програма Android (яка не є системним додатком)?

Це залежить від пристрою. getMemoryClass()onActivityManager дасть вам значення для пристрою, на якому працює ваш код.

Чи є різниці між версіями Android?

Так, якщо вимоги до ОС збільшуються з роками, і пристрої повинні підлаштовуватися під відповідність.

Чи є відмінності щодо виробника пристрою?

Так, наскільки виробники виготовляють пристрої, і розмір залежить від пристрою.

Які "побічні фактори" враховуються при визначенні, скільки оперативної пам’яті може використовувати додаток?

Я поняття не маю, що означає "побічні фактори".

Ранні пристрої мали обмеження на 16 МБ; Пізніше пристрої збільшили це до 24 Мб або 32 МБ

Це приблизно так. Роздільна здатність екрана є важливим фактором, оскільки більші роздільні здатності означають більші растрові карти, і тому планшети та телефони з високою роздільною здатністю ще мають більш високі значення. Наприклад, ви побачите пристрої з набором 48 Мб, і я не здивуюсь, якщо є значення, що перевищують це.

Як можливо, що додатки перевищують цю межу?

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

Незважаючи на це, нативний код (NDK) не підпадає під обмеження купи. А оскільки Android 3.0 програми можуть запитувати «велику купу», як правило, в межах сотень МБ, але це вважається поганою формою для більшості програм.

Крім того, я помітив, що деякі програми моєї аварії виходять із OutOfMemoryException при використанні близько 30-40 мегабайт.

Майте на увазі, що збирач сміття Android не є компактним збирачем сміття. Виняток насправді повинен бути CouldNotFindSufficientlyLargeBlockOfMemoryException, але це, мабуть, вважалося занадто багатослівним. OutOfMemoryExceptionозначає, що ви не можете виділити запитуваний блок , не те, що ви повністю вичерпали свою купу.


Я не можу зрозуміти про таблицю, у мене мобільний Xperia X, який має роздільну здатність приблизно 1080 x 1920, що має велику роздільну здатність, і інший пристрій Samsung Tab 4, роздільна здатність якого становить 800 x 1280. 3 Гб оперативної пам’яті та вкладки поставляється з 1,5 ГБ оперативної пам’яті, тому планшет займає великий оперативної пам’яті через великий екран?
Рахул Мандалія

@RahulMandaliya: Мені дуже шкода, але я не розумію вашої турботи чи того, що це стосується цього питання. Ви можете відкрити окреме запитання щодо переповнення стека, де ви детально поясните, що вас викликає.
CommonsWare

15

Кінець 2018 року, тому все змінилося.

Перш за все: запустіть додаток і відкрийте вкладку Android Profiler в Android Studio. Ви побачите, скільки пам'яті вона споживає, ви здивуєтеся, але це може виділити багато оперативної пам’яті.

Також тут відмінна стаття в офіційних документах з детальними інструкціями щодо використання програми Profiler Memory, яка може дати тобі глибокий погляд на управління пам'яттю.

Але в більшості випадків вам буде достатньо вашого звичайного Android Profiler.

введіть тут опис зображення

Зазвичай додаток починається з виділення 50 Мб оперативної пам'яті, але миттєво підскакує до 90 Мб, коли ви починаєте завантажувати фотографії в пам'ять. Якщо ви відкриєте «Активність» у ViewPager із попередньо завантаженими фотографіями (3,5 Мбіт кожна), ви легко зможете отримати 190 Мб за секунди.

Але це не означає, що у вас є проблеми з управлінням пам'яттю.

Найкраща порада, яку я можу дати, - це дотримуватися вказівок та найкращих практик, використовувати топ-бібліотеки для завантаження зображень (Glide, Picasso), і ти будеш добре.


Але якщо вам потрібно щось підготувати, і вам дійсно потрібно знати, скільки пам'яті ви можете виділити вручну, ви можете отримати загальну вільну пам'ять і обчислити заздалегідь визначену частину (у%). У моєму випадку мені потрібно було кешувати дешифровані фотографії в пам’яті, тому мені не потрібно розшифровувати їх щоразу, коли користувач ковзає по списку.

Для цього можна використовувати готовий до використання клас LruCache . Це клас кешу, який автоматично відстежує кількість пам'яті, яку виділяють ваші об’єкти (або кількість примірників), і видаляє найдавніші, щоб зберегти останні за історією їх використання. Ось чудовий підручник про те, як ним користуватися.

У моєму випадку я створив 2 екземпляри кеш-пам'яті: для великих пальців та вкладених файлів. Зробив їх статичними з однотонним доступом, щоб вони були доступні у всьому світі через програму.

клас кеша:

public class BitmapLruCache extends LruCache<Uri, byte[]> {

    private static final float CACHE_PART_FOR_THUMBS_PRC = 0.01f; // 1% (Nexus 5X - 5Mb)
    private static final float CACHE_PART_FOR_ATTACHMENTS_PRC = 0.03f;// 3% (Nexus 5X - 16Mb)
    private static BitmapLruCache thumbCacheInstance;
    private static BitmapLruCache attachmentCacheInstance;

public static synchronized BitmapLruCache getDecryptedThumbCacheInstance() {
    if (thumbCacheInstance == null) {

        int cacheSize = getCacheSize(CACHE_PART_FOR_THUMBS_PRC);
    //L.log("creating BitmapLruCache for Thumb with size: " + cacheSize + " bytes");
        thumbCacheInstance = new BitmapLruCache(cacheSize);
        return thumbCacheInstance;
    } else {
        return thumbCacheInstance;
    }
}

public static synchronized BitmapLruCache getDecryptedAttachmentCacheInstance() {
    if (attachmentCacheInstance == null) {

        int cacheSize = getCacheSize(CACHE_PART_FOR_ATTACHMENTS_PRC);
    //            L.log("creating BitmapLruCache for Attachment with size: " + cacheSize + " bytes");
        attachmentCacheInstance = new BitmapLruCache(cacheSize);
        return attachmentCacheInstance;
    } else {
        return attachmentCacheInstance;
    }
}

private BitmapLruCache(int maxSize) {
    super(maxSize);
}

public void addBitmap(Uri uri, byte[] bitmapBytes) {
    if (get(uri) == null && bitmapBytes != null)
        put(uri, bitmapBytes);
}

public byte[] getBitmap(Uri uri) {
    return get(uri);
}


@Override
protected int sizeOf(Uri uri, byte[] bitmapBytes) {
    // The cache size will be measured in bytes rather than number of items.
    return bitmapBytes.length;
}
}

Ось як я обчислюю наявну безкоштовну оперативну пам’ять і скільки я можу з неї перекусити:

private static int getCacheSize(float partOfTotalFreeMemoryToUseAsCache){
    final long maxMemory = Runtime.getRuntime().maxMemory();
    //Use ... of available memory for List Notes thumb cache
    return (int) (maxMemory * partOfTotalFreeMemoryToUseAsCache);
}

Ось так я використовую його в Adapters, щоб отримати кешоване зображення:

byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);

і як я встановив його в кеш у фоновому потоці (звичайний AsyncTask):

BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes); 

Мій додаток орієнтовано на API 19+, тому пристрої не старі, і ці частини доступної оперативної пам’яті досить хороші для кешу в моєму випадку (1% та 3%).

Факт забави: Android не має ніяких API та інших хак-файлів, щоб отримати обсяг пам’яті, що виділяється вашому додатку, він розраховується на льоту, виходячи з різних факторів.


PS Я використовую статичне поле класу для зберігання кешу, але відповідно до останніх інструкцій Android рекомендується використовувати для цього компонент архітектури ViewModel .


12

Обмеження пам’яті на додаток тут залежно від розміру екрана та версії Android: https://drive.google.com/file/d/0B7Vx1OvzrLa3Y0R0X1BZbUpicGc/view?usp=sharing

Джерело: Завантаження програм для сумісності Android http://source.android.com/compatibility/downloads.html ; Документ на визначення сумісності (CDD), сумісність розділу віртуальної машини або сумісність під час виконання


2
URL-адреса диска запитує дозвіл доступу
silent_grave
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.