ios ios应用最大内存预算
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5887248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ios app maximum memory budget
提问by frilla
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).
我正在开发一款至少针对 3gs 的 ios 游戏。我们将高清资产用于视网膜显示设备(iphone 4、ipod touch 第 4 代)。
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.
内存方面,Ipod Touch 4th gen 对我们来说似乎是最受限制的设备,因为它具有与 3gs 相同数量的 RAM(与 Iphone 4 的 512 相比为 256),但我们在其上使用了高清资产。该应用程序曾经在尝试加载 100-110 MB 的内存时崩溃,但现在我们降到了 70 MB,我们从来没有加载崩溃。
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.
经过大量搜索,似乎没有官方硬性限制,那么我们应该如何知道使用什么内存预算才能安全?我们希望能够为美术师提供一个他们可以使用的预算,而无需担心每张地图的内存问题。
采纳答案by Max
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.
我想你已经回答了你自己的问题:尽量不要超过 70 Mb 的限制,但这实际上取决于很多事情:你使用的是什么 iOS 版本(不是 SDK),有多少应用程序在后台运行,确切的内存是多少你正在使用等
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.
只是避免即时内存飞溅(例如,您正在使用 40 Mb 的 RAM,然后分配 80 Mb 的更多用于一些短计算)。在这种情况下,iOS 会立即终止您的应用程序。
You should also consider lazy loading of assets (load them only when you really need and not beforehand).
您还应该考虑延迟加载资产(仅在您真正需要时而不是事先加载它们)。
回答by Jasper
Results of testing with the utility Split wrote (link is in his answer):
使用 Split 写的实用程序进行测试的结果(链接在他的回答中):
device: (crash amount/total amount/percentage of total)
设备:(崩溃量/总量/总量百分比)
- iPad1: 127MB/256MB/49%
- 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: 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)
- iPad Pro 11.0” (2018): 2858/3769/76% (iOS 12.1)
- iPad Pro 12.9” (2018, 1TB): 4598/5650/81% (iOS 12.1)
- iPad 10.2: 1844/2998/62% (iOS 13.2.3)
- 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: 1396MB/2048MB/68% (iOS 9.2)
- iPhone6s+: 1392MB/2048MB/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)
- iPhone8: 1364/1990MB/70% (iOS 12.1)
- iPhone X: 1392/2785/50% (iOS 11.2.1)
- iPhone XS: 2040/3754/54% (iOS 12.1)
- iPhone XS Max: 2039/3735/55% (iOS 12.1)
- iPhone XR: 1792/2813/63% (iOS 12.1)
- iPhone 11: 2068/3844/54% (iOS 13.1.3)
- iPhone 11 Pro Max: 2067/3740/55% (iOS 13.2.3)
- iPad1:127MB/256MB/49%
- iPad2:275MB/512MB/53%
- iPad3:645MB/1024MB/62%
- iPad4:585MB/1024MB/57% (iOS 8.1)
- iPad Mini 第一代:297MB/512MB/58%
- iPad Mini 视网膜: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)
- iPad Pro 11.0” (2018):2858/3769/76% (iOS 12.1)
- iPad Pro 12.9”(2018 年,1TB):4598/5650/81%(iOS 12.1)
- iPad 10.2:1844/2998/62%(iOS 13.2.3)
- iPod touch 第 4 代:130MB/256MB/51% (iOS 6.1.1)
- iPod touch 第 5 代: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:1396MB/2048MB/68% (iOS 9.2)
- iPhone6s+:1392MB/2048MB/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)
- iPhone8:1364/1990MB/70% (iOS 12.1)
- iPhone X:1392/2785/50%(iOS 11.2.1)
- iPhone XS:2040/3754/54%(iOS 12.1)
- iPhone XS Max:2039/3735/55% (iOS 12.1)
- iPhone XR:1792/2813/63%(iOS 12.1)
- iPhone 11:2068/3844/54%(iOS 13.1.3)
- iPhone 11 Pro Max:2067/3740/55% (iOS 13.2.3)
回答by Split
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.
我创建了一个小实用程序,它尝试分配尽可能多的内存以防止崩溃,并记录发生内存警告和崩溃的时间。这有助于找出任何 iOS 设备的内存预算。
回答by cprcrack
In my app, user experience is better if more memory is used, so I have to decide if I really should free allthe 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).
在我的应用程序中,如果使用更多内存,用户体验会更好,因此我必须决定是否真的应该释放所有内存didReceiveMemoryWarning
。根据 Split 和 Jasper Pol 的回答,最多使用总设备内存的 45% 似乎是一个安全阈值(谢谢大家)。
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
}
回答by Harsh
By forking SPLITS repo, I built one to test iOS memory that can be allocated to the Today's Extension
通过 fork SPLITS repo,我构建了一个来测试可以分配给 Today's Extension 的 iOS 内存
iOSMemoryBudgetTestForExtension
iOSMemoryBudgetTestForExtension
Following is the result that i got in iPhone 5s
以下是我在 iPhone 5s 中得到的结果
Memory Warning at 10 MB
10 MB 时的内存警告
App Crashed at 12 MB
应用程序在 12 MB 时崩溃
By this means Apple is merely allowing any extensions to work with their full potential.
通过这种方式,Apple 只是允许任何扩展充分发挥其潜力。
回答by Kobski
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.
您应该观看WWDC 2010 Session 视频中的session 147 。它是“iPhone OS 上的高级性能优化,第 2 部分”。
有很多关于内存优化的好建议。
Some of the tips are:
一些提示是:
- Use nested
NSAutoReleasePool
s to make sure your memory usage does not spike. - Use
CGImageSource
when creating thumbnails from large images. - Respond to low memory warnings.
- 使用嵌套
NSAutoReleasePool
s 来确保您的内存使用不会激增。 CGImageSource
在从大图像创建缩略图时使用。- 响应低内存警告。
回答by Exaberri Tokugawa
Starting with iOS13, there is an Apple-supported way of querying this by using
从 iOS13 开始,有一种 Apple 支持的查询方式,可以使用
#include <os/proc.h>
size_t os_proc_available_memory(void)
Introduced here: https://developer.apple.com/videos/play/wwdc2019/606/
这里介绍:https: //developer.apple.com/videos/play/wwdc2019/606/
Around min 29-ish.
大约 29 分钟。
Edit: Adding link to documentation https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc
编辑:添加文档链接 https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc
回答by Dmitry Preobrazhenskiy
- (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
如果使用 TASK_BASIC_INFO_COUNT 而不是 MACH_TASK_BASIC_INFO,你会得到
kerr == KERN_INVALID_ARGUMENT (4)
kerr == KERN_INVALID_ARGUMENT (4)
回答by Slyv
I created one more list by sorting Jaspers list by device RAM (I made my own tests with Split's tool and fixed some results - check my comments in Jaspers thread).
我通过按设备 RAM 对 Jaspers 列表进行排序来创建另一个列表(我使用 Split 的工具进行了自己的测试并修复了一些结果 - 检查我在 Jaspers 线程中的评论)。
device RAM: percent range to crash
设备 RAM:崩溃的百分比范围
- 256MB: 49% - 51%
- 512MB: 53% - 63%
- 1024MB: 57% - 68%
- 2048MB: 68% - 69%
- 3072MB: 63% - 66%
- 4096MB: 77%
- 6144MB: 81%
- 256MB:49% - 51%
- 512MB:53% - 63%
- 1024MB:57% - 68%
- 2048MB:68% - 69%
- 3072MB:63% - 66%
- 4096MB:77%
- 6144MB:81%
Special cases:
特别案例:
- iPhone X (3072MB): 50%
- iPhone XS/XS Max (4096MB): 55%
- iPhone XR (3072MB): 63%
- iPhone 11/11 Pro Max (4096MB): 54% - 55%
- iPhone X (3072MB):50%
- iPhone XS/XS Max (4096MB):55%
- iPhone XR (3072MB):63%
- iPhone 11/11 Pro Max (4096MB):54% - 55%
Device RAM can be read easily:
可以轻松读取设备 RAM:
[NSProcessInfo processInfo].physicalMemory
From my experience it is safe to use 45% for 1GB devices, 50% for 2/3GB devices and 55% for 4GB devices. Percent for macOS can be a bit bigger.
根据我的经验,1GB 设备使用 45%,2/3GB 设备使用 50%,4GB 设备使用 55% 是安全的。macOS 的百分比可能更大一些。
回答by App Dev Guy
Working with the many answers above, I have implemented Apples new method os_proc_available_memory()
for iOS 13+ coupled with NSByteCountFormatter
which offers a number of useful formatting options for nicer output of the memory:
使用上面的许多答案,我已经os_proc_available_memory()
为 iOS 13+实现了 Apple 的新方法,NSByteCountFormatter
并提供了许多有用的格式化选项,以更好地输出内存:
#include <os/proc.h>
....
- (NSString *)memoryStringForBytes:(unsigned long long)memoryBytes {
NSByteCountFormatter *byteFormatter = [[NSByteCountFormatter alloc] init];
byteFormatter.allowedUnits = NSByteCountFormatterUseGB;
byteFormatter.countStyle = NSByteCountFormatterCountStyleMemory;
NSString *memoryString = [byteFormatter stringFromByteCount:memoryBytes];
return memoryString;
}
- (void)memoryLoggingOutput {
if (@available(iOS 13.0, *)) {
NSLog(@"Physical memory available: %@", [self memoryStringForBytes:[NSProcessInfo processInfo].physicalMemory]);
NSLog(@"Memory A (brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory()]);
NSLog(@"Memory B (no brackets): %@", [self memoryStringForBytes:(long)os_proc_available_memory]);
}
}
Important note: Do not forget the ()
at the end.I have included both NSLog
options in in the memoryLoggingOutput
method because it does not warn you that they are missing and failure to include the brackets returns an unexpected yet constant result.
重要提示:不要忘记()
结尾。我NSLog
在memoryLoggingOutput
方法中包含了这两个选项,因为它不会警告您它们丢失,并且不包含括号会返回意外但恒定的结果。
The string returned from the method memoryStringForBytes
outputs values like so:
从方法返回的字符串memoryStringForBytes
输出如下值:
NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.93 GB
// 2 seconds later
NSLog(@"%@", [self memoryStringForBytes:(long)os_proc_available_memory()]); // 1.84 GB