Максимальный объем памяти ios app

Я работаю над игрой ios, нацеленной как минимум на 3gs. Мы используем HD-ресурсы для устройств отображения сетчатки (iphone 4, ipod touch 4-го поколения).

Память мудрая, Ipod Touch 4-го поколения, по-видимому, является самым ограничивающим устройством для нас, поскольку у него одинаковое количество оперативной памяти (256 по сравнению с Iphone 4 512) как 3gs, но мы используем на нем HD-ресурсы. Приложение, используемое для сбоя при попытке загрузить 100-110 МБ оперативной памяти, но теперь, когда мы до 70 МБ, у нас никогда не было сбоя загрузки.

После многого поиска вокруг, кажется, нет официального жесткого ограничения, так как мы должны знать, какой бюджет памяти использовать, чтобы быть в безопасности? Мы хотим, чтобы дать художникам бюджет, который они могут использовать без проблем памяти для каждой карты.

Ответ 1

Я думаю, что вы ответили на свой вопрос: постарайтесь не превышать лимит в 70 Мб, однако это действительно зависит от многих вещей: какая версия iOS вы используете (не SDK), сколько приложений работает в фоновом режиме, какую именно память вы используете и т.д.

Просто избегайте мгновенных всплесков памяти (например, вы используете 40 Мб ОЗУ, а затем выделяете 80 Мб больше для небольшого вычисления). В этом случае iOS немедленно убьет ваше приложение.

Вы также должны учитывать ленивую загрузку активов (загружать их только тогда, когда вам действительно нужно, а не заранее).

Ответ 2

Результаты тестирования с помощью утилиты Split (ссылка в его ответе):

устройство: (сумма сбоя/общая сумма/процент от общего количества)

  • iPad1:127MB/256MB/49%
  • iPad2: 275MB/512MB/53%
  • iPad3: 645 МБ /1024 МБ /62%
  • iPad4: 585MB/1024MB/57% (iOS 8.1)
  • iPad Mini 1st Generation: 297MB/512MB/58%
  • iPad Mini retina: 696MB/1024MB/68% (iOS 7.1)
  • iPad Air: 697MB/1024MB/68%
  • iPad Air 2: 1383MB/2048MB/68% (iOS 10.2.1)
  • iPad Pro 9.7 ": 1395MB/1971MB/71% (iOS 10.0.2 (14A456))
  • iPad Pro 10.5 ": 3057/4000/76% (iOS 11 beta4)
  • iPad Pro 12,9 "(2015): 3058/3999/76% (iOS 11.2.1)
  • iPad Pro 12,9 "(2017): 3057/3974/77% (iOS 11 beta4)
  • iPod touch 4-го поколения: 130 МБ /256 МБ /51% (iOS 6.1.1)
  • iPod touch 5-го поколения: 286 МБ /512 МБ /56% (iOS 7.0)
  • iPhone4: 325MB/512MB/63%
  • iPhone4s: 286MB/512MB/56%
  • iPhone5: 645 МБ /1024 МБ /62%
  • iPhone5s: 646MB/1024MB/63%
  • iPhone6: 645MB/1024MB/62% (iOS 8.x)
  • iPhone6+: 645 МБ /1024 МБ /62% (iOS 8.x)
  • iPhone6s: 1396MB/2048MB/68% (iOS 9.2)
  • iPhone6s+: 1392 МБ /2048 МБ /68% (iOS 10.2.1)
  • iPhoneSE: 1395MB/2048MB/69% (iOS 9.3)
  • iPhone7: 1395/2048MB/68% (iOS 10.2)
  • iPhone7+: 2040MB/3072MB/66% (iOS 10.2.1)
  • iPhone X: 1392/2785/50% (iOS 11.2.1)

Ответ 3

Я создал небольшую утилиту, которая пытается выделить как можно больше памяти для сбоя, и она записывает, когда произошли сбои памяти и сбои. Это помогает узнать, какой бюджет памяти для любого устройства iOS.

https://github.com/Split82/iOSMemoryBudgetTest

Ответ 4

В моем приложении пользовательский интерфейс лучше, если используется больше памяти, поэтому я должен решить, действительно ли я должен освободить всю память, которую я могу, в didReceiveMemoryWarning. Основываясь на ответе Split и Jasper Pol, использование максимально 45% общей памяти устройства является безопасным порогом (спасибо ребятам).

Если кто-то хочет посмотреть мою фактическую реализацию:

#import "mach/mach.h"

- (void)didReceiveMemoryWarning
{
    // Remember to call super
    [super didReceiveMemoryWarning];

    // If we are using more than 45% of the memory, free even important resources,
    // because the app might be killed by the OS if we don't
    if ([self __getMemoryUsedPer1] > 0.45)
    {
        // Free important resources here
    }

    // Free regular unimportant resources always here
}

- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

Swift (на основе этого ответа):

func __getMemoryUsedPer1() -> Float
{
    let MACH_TASK_BASIC_INFO_COUNT = (sizeof(mach_task_basic_info_data_t) / sizeof(natural_t))
    let name = mach_task_self_
    let flavor = task_flavor_t(MACH_TASK_BASIC_INFO)
    var size = mach_msg_type_number_t(MACH_TASK_BASIC_INFO_COUNT)
    var infoPointer = UnsafeMutablePointer<mach_task_basic_info>.alloc(1)
    let kerr = task_info(name, flavor, UnsafeMutablePointer(infoPointer), &size)
    let info = infoPointer.move()
    infoPointer.dealloc(1)
    if kerr == KERN_SUCCESS
    {
        var used_bytes: Float = Float(info.resident_size)
        var total_bytes: Float = Float(NSProcessInfo.processInfo().physicalMemory)
        println("Used: \(used_bytes / 1024.0 / 1024.0) MB out of \(total_bytes / 1024.0 / 1024.0) MB (\(used_bytes * 100.0 / total_bytes)%%)")
        return used_bytes / total_bytes
    }
    return 1
}

Ответ 5

Разбирая SPLITS repo, я построил один, чтобы протестировать память iOS, которая может быть выделена для Today Extension

iOSMemoryBudgetTestForExtension

Ниже приведен результат, который я получил в iPhone 5s

Предупреждение о безопасности при 10 МБ

Приложение разбилось на 12 МБ

Таким образом, Apple просто позволяет всем расширениям работать с полным потенциалом.

Ответ 6

Вы должны смотреть сеанс 147 из видеозаписей WWDC 2010. Это "Расширенная оптимизация производительности на iPhone OS, часть 2".
Существует много хороших советов по оптимизации памяти.

Некоторые из советов:

  • Используйте вложенный NSAutoReleasePool, чтобы убедиться, что использование вашей памяти не всплывает.
  • Используйте CGImageSource при создании эскизов больших изображений.
  • Отвечайте на предупреждения о низкой памяти.

Ответ 7

- (float)__getMemoryUsedPer1
{
    struct mach_task_basic_info info;
    mach_msg_type_number_t size = MACH_TASK_BASIC_INFO;
    kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size);
    if (kerr == KERN_SUCCESS)
    {
        float used_bytes = info.resident_size;
        float total_bytes = [NSProcessInfo processInfo].physicalMemory;
        //NSLog(@"Used: %f MB out of %f MB (%f%%)", used_bytes / 1024.0f / 1024.0f, total_bytes / 1024.0f / 1024.0f, used_bytes * 100.0f / total_bytes);
        return used_bytes / total_bytes;
    }
    return 1;
}

Если вы используете TASK_BASIC_INFO_COUNT вместо MACH_TASK_BASIC_INFO, вы получите

kerr == KERN_INVALID_ARGUMENT (4)

Ответ 8

Я создал еще один список, отсортировав список Jaspers оперативной памятью (я сделал свои собственные тесты с помощью инструмента Split и исправил некоторые результаты - проверьте мои комментарии в этом потоке).

RAM устройства: диапазон процентов для сбоя

  • 256 МБ: 49% - 51%
  • 512 МБ: 53% - 63%
  • 1024 МБ: 57% - 68%
  • 2048 МБ: 68% - 69%
  • 3072 МБ: 66%
  • 4096 МБ: 77%

Особый случай:

  • iPhone X (3072 МБ): 50%

ОЗУ устройства можно легко прочитать:

[NSProcessInfo processInfo].physicalMemory

По моему опыту безопасно использовать 45% для устройств 1 ГБ, 50% для устройств 2/3 ГБ и 55% для устройств 4 ГБ. Процент для macOS может быть немного больше.