ios app maximum memory budget

本文讨论了iOS应用在不同设备上的最大可用内存预算,通过实际测试提供了各设备的内存使用上限,并探讨了如何避免因内存不足导致的应用崩溃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

I'm working on an ios game that's targeting as a minimum the 3gs. We are using HD assets for retina display devices (iphone 4, ipod touch 4th gen).

Memory wise, Ipod Touch 4th gen seems to be the most constraint device for us since it has the same amount of RAM (256 compared to Iphone 4's 512) as 3gs but we're using HD assets on it. The app used to crash when trying to load 100-110mb of ram but now that we're down to 70MB, we've never had loading crash.

After lots of searching around, there seems to be no official hard limit so how should we go about knowing what memory budget to use to be safe? We want to be able to give the artists a budget they can use without memory worries for each map.

share improve this question
 

7 Answers

up vote 24 down vote accepted

I think you've answered your own question: try not to go beyond the 70 Mb limit, however it really depends on many things: what iOS version you're using (not SDK), how many applications running in background, what exact memory you're using etc.

Just avoid the instant memory splashes (e.g. you're using 40 Mb of RAM, and then allocating 80 Mb's more for some short computation). In this case iOS would kill your application immediately.

You should also consider lazy loading of assets (load them only when you really need and not beforehand).

share improve this answer
 
2 
It's just that we wanted to put as much stuff as we could (graphics & sounds). Artists will always want to put as much as they possibly can into a game that's why I want to limit them with a budget. I guess we'll just have to test on many different devices in different settings to find a reasonable maximum memory footprint to use. –  frilla  May 5 '11 at 0:42 
2 
Will allocating only 70MB (which is presumably under the budget) at any time on that device (even after heavy usage in other memory-hungry apps) always guarantee a successful allocation, or will it potentially still crash? –  Steven Lu  Sep 3 '13 at 23:29
1 
@Steven Lu it depends on your device. E.g. on newer ones, like iPhone5 or iPad4 70 Mb allocation is not a problem at all. –  Max  Sep 4 '13 at 9:55
1 
yes but i want to know if I can be sure that as long as I keep my app's total usage under the magical device specific memory budget that it will not get terminated! –  Steven Lu  Sep 4 '13 at 16:52 
1 
there are no guarantees –  Max  Sep 4 '13 at 18:49

I did some testing with the utility Split wrote (link is in his answer).

I don't have all devices available but this is what I could test so far:

  • iPad1: 127MB/256MB/49% (crash amount/total amount/percentage of total)
  • iPad2: 275MB/512MB/53%
  • iPad3: 645MB/1024MB/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: 1195MB/2048MB/58% (iOS 8.x)
  • iPod touch 4th gen: 130MB/256MB/51% (iOS 6.1.1)
  • iPod touch 5th gen: 286MB/512MB/56% (iOS 7.0)
  • iPhone4: 325MB/512MB/63%
  • iPhone4S: 286MB/512MB/56%
  • iPhone5: 645MB/1024MB/62%
  • iPhone5S: 646MB/1024MB/63%
  • iPhone6: 645MB/1024MB/62% (iOS 8.x)
  • iPhone6+: 645MB/1024MB/62% (iOS 8.x)
  • iPhone6s: 1195MB/2048MB/58% (theoretical, untested)
  • iPhone6s+: 1195MB/2048MB/58% (theoretical, untested)
share improve this answer
 
1 
iPhone4: similar value confirmed, seems legit :P –  cprcrack  Oct 30 '13 at 19:53
 
By the way, this app is also VERY useful to test state restoration in a real device, because it causes other apps to be freed from memory. –  cprcrack  Nov 1 '13 at 11:21
3 
iPhone 5 crashes at ±645 MB. –  asp_net  Dec 15 '13 at 21:03
 
iPhone 5S crashes at ±646 MB pretty reliably here. –  eAi  Oct 3 '14 at 13:30
3 
@JasperPol I've edited your post to include various devices I have, I hope that's okay. I've added the iOS version I tested on in case it matters, but feel free to remove it if you think it's not important. –  JosephH  Nov 18 '14 at 16:32

I created small utility which tries to allocate as much memory as possible to crash and it records when memory warnings and crash happened. This helps to find out what's the memory budget for any iOS device.

https://github.com/Split82/iOSMemoryBudgetTest

share improve this answer
 

In my app, user experience is better if more memory is used, so I have to decide if I really should freeall the memory I can in didReceiveMemoryWarning. Based on Split's and Jasper Pol's answer, using a maximum of 45% of the total device memory appears to be a safe threshold (thanks guys).

In case someone wants to look at my actual implementation:

#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 (based on this answer):

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
}
share improve this answer
 
1 
size should be TASK_BASIC_INFO_COUNT instead of sizeof(info) - this mistake copy-pasted to many places with same code –  Speakus  Dec 2 '13 at 1:13
 
Thanks Speakus. You seem to be right based on this link. Do you have any other reference where this information can be found? –  cprcrack  Dec 2 '13 at 23:21
 
apple uses TASK_BASIC_INFO_COUNT too –  Speakus  Dec 3 '13 at 3:12

You should watch session 147 from the WWDC 2010 Session videos. It is "Advanced Performance Optimization on iPhone OS, part 2".
There is a lot of good advice on memory optimizations.

Some of the tips are:

  • Use nested NSAutoReleasePools to make sure your memory usage does not spike.
  • Use CGImageSource when creating thumbnails from large images.
  • Respond to low memory warnings.
share improve this answer
 
 
My question is not about how to optimize (thanks for the link though), it's about how much can we allow ourselves to use. The reason is that for example, if we optimize to gain 20mb, then artists will want to use that 20mb if it's within the reasonable "budget", aka sure that it won't cause any performance issues or memory crash. –  frilla  May 5 '11 at 0:20
 
OK. The crash will be because the OS is terminating the app because of constrained memory. You could just add an NSLog inside didReceiveMemoryWarning and then do some testing where you allocate different amounts of memory and then see when the memory warnings start to kick in. –  Kobski  May 5 '11 at 6:13
- (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;
}

If one will use TASK_BASIC_INFO_COUNT instead of MACH_TASK_BASIC_INFO, you will get

kerr == KERN_INVALID_ARGUMENT (4)

share improve this answer
 

By forking SPLITS repo, I built one to test iOS memory that can be allocated to the Today's Extension

iOSMemoryBudgetTestForExtension

Following is the result that i got in iPhone 5s

Memory Warning at 10 MB

App Crashed at 12 MB

By this means Apple is merely allowing any extensions to work with their full potential.

share improve this answer
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值