Ich arbeite an einem iOS-Spiel, das mindestens 3gs zum Ziel hat. Wir verwenden HD-Assets für Retina-Anzeigegeräte (iPhone 4, iPod touch 4. Generation).
In Bezug auf den Speicher scheint der iPod Touch der 4. Generation für uns das Gerät mit den meisten Einschränkungen zu sein, da er die gleiche Menge an RAM (256 im Vergleich zu Iphone 4 512)) wie 3G hat, aber wir verwenden HD-Assets Die App stürzte ab, als versucht wurde, 100-110 MB RAM zu laden.
Nach vielen Recherchen scheint es keine offizielle Beschränkung zu geben. Wie sollten wir also vorgehen, um zu wissen, welches Speicherbudget verwendet werden muss, um sicher zu gehen? Wir möchten den Künstlern ein Budget zur Verfügung stellen, das sie ohne Speicherprobleme für jede Karte verwenden können.
Ich denke, Sie haben Ihre eigene Frage beantwortet: Versuchen Sie, die Grenze von 70 MB nicht zu überschreiten, aber es hängt wirklich von vielen Dingen ab: Welche iOS-Version Sie verwenden (nicht SDK), wie viele Anwendungen im Hintergrund ausgeführt werden, welcher genaue Speicher du benutzt etc.
Vermeiden Sie einfach die sofortigen Speicherspritzer (z. B. verwenden Sie 40 MB RAM und weisen dann 80 MB mehr für eine kurze Berechnung zu). In diesem Fall würde iOS Ihre Anwendung sofort beenden.
Sie sollten auch ein verzögertes Laden von Assets in Betracht ziehen (laden Sie diese nur, wenn Sie sie wirklich benötigen und nicht vorher).
Testergebnisse mit dem Dienstprogramm Split schrieb (Link ist in seiner Antwort):
Gerät: (Crash-Menge/Gesamtmenge/Prozentsatz der Gesamtmenge)
Ich habe ein kleines Dienstprogramm erstellt, das versucht, so viel Speicher wie möglich für Abstürze zuzuweisen. Es zeichnet auf, wann Speicherwarnungen und Abstürze aufgetreten sind. Auf diese Weise können Sie das Speicherbudget für jedes iOS-Gerät ermitteln.
In meiner App ist die Benutzererfahrung besser, wenn mehr Speicher verwendet wird. Daher muss ich entscheiden, ob ich wirklich alle den Speicher freigeben soll, den ich in didReceiveMemoryWarning
verwenden kann. Basierend auf der Antwort von Split und Jasper Pol scheint die Verwendung von maximal 45% des gesamten Gerätespeichers eine sichere Schwelle zu sein (danke Jungs).
Für den Fall, dass sich jemand meine aktuelle Implementierung ansehen möchte:
#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 (basierend auf diese Antwort ):
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
}
Indem ich SPLITS repo gegabelt habe, habe ich einen erstellt, um den iOS-Speicher zu testen, der der Today's Extension zugewiesen werden kann
iOSMemoryBudgetTestForExtension
Das folgende ist das Ergebnis, das ich in iPhone 5s erhielt
Speicherwarnung bei 10 MB
App bei 12 MB abgestürzt
Auf diese Weise Apple lässt lediglich zu, dass alle Erweiterungen ihr volles Potenzial entfalten.
Sie sollten Sitzung 147 in den WWDC 2010-Sitzungsvideos ansehen. Es ist "Advanced Performance Optimization auf dem iPhone OS, Teil 2".
Es gibt viele gute Ratschläge zur Speicheroptimierung.
Einige der Tipps sind:
NSAutoReleasePool
s, um sicherzustellen, dass die Speichernutzung nicht zu stark ansteigt.CGImageSource
, um aus großen Bildern Miniaturansichten zu erstellen.- (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;
}
Wenn Sie TASK_BASIC_INFO_COUNT anstelle von MACH_TASK_BASIC_INFO verwenden, erhalten Sie
kerr == KERN_INVALID_ARGUMENT (4)
Ich habe eine weitere Liste erstellt, indem ich die Jaspers-Liste nach Gerät sortiert habe RAM (Ich habe meine eigenen Tests mit dem Tool von Split durchgeführt und einige Ergebnisse korrigiert - siehe meine Kommentare im Jaspers-Thread).
Geräte-RAM: Prozentbereich bis zum Absturz
Spezialfälle:
Gerät RAM kann leicht gelesen werden:
[NSProcessInfo processInfo].physicalMemory
Aus meiner Erfahrung ist es sicher, 45% für 1-GB-Geräte, 50% für 2/3-GB-Geräte und 55% für 4-GB-Geräte zu verwenden. Der Prozentsatz für macOS kann etwas größer sein.