ios uygulaması maksimum bellek bütçesi


152

Minimum 3gs hedefleyen bir ios oyunu üzerinde çalışıyorum. Retina ekran cihazları (iphone 4, ipod touch 4th gen) için HD varlıkları kullanıyoruz.

Bellek açısından, Ipod Touch 4. nesil bizim için en kısıtlayıcı cihaz gibi görünüyor, çünkü 3gs ile aynı miktarda RAM'e (Iphone 4'ün 512'sine göre 256) sahip ama üzerinde HD varlıkları kullanıyoruz. Uygulama 100-110mb ram yüklemeye çalışırken çöküyordu, ancak şimdi 70MB'a düştüğümüze göre, asla yükleme çökmesi olmadı.

Birçok arama yaptıktan sonra resmi bir sabit sınır yok gibi görünüyor, bu yüzden güvenli olmak için hangi bellek bütçesinin kullanılacağını nasıl bilmeliyiz? Sanatçılara her harita için hafıza kaygısı olmadan kullanabilecekleri bir bütçe vermek istiyoruz.



14
Bu sorunun, daha sonra sorulan bir şeyin nasıl bir kopyası olabileceğinden emin değilim.
Jasper

Yanıtlar:


42

Sanırım kendi sorunuzu cevapladınız: 70 Mb sınırını aşmamaya çalışın, ancak gerçekten birçok şeye bağlıdır: kullandığınız iOS sürümü (SDK değil), arka planda kaç uygulama çalışıyor, tam olarak hangi bellek kullanıyorsunuz vb.

Anlık bellek sıçramalarından kaçının (örneğin, 40 Mb RAM kullanıyorsunuz ve daha sonra bazı kısa hesaplama için 80 Mb daha fazla ayırıyorsunuz). Bu durumda iOS uygulamanızı derhal öldürür.

Ayrıca, varlıkların tembel olarak yüklenmesini de göz önünde bulundurmalısınız (bunları yalnızca önceden ihtiyacınız olduğunda ve gerçekten ihtiyacınız olduğunda yükleyin).


2
Sadece olabildiğince fazla şey koymak istedik (grafikler ve sesler). Sanatçılar bir oyuna her zaman mümkün olduğu kadar koymak isteyeceklerdir, bu yüzden onları bir bütçeyle sınırlamak istiyorum. Sanırım makul bir maksimum bellek alanı bulmak için farklı ortamlarda birçok farklı cihazı test etmemiz gerekecek.
frilla

2
Bu cihazda herhangi bir zamanda yalnızca 70 MB (ki muhtemelen bütçenin altında) tahsis edilecek mi (diğer hafızaya aç uygulamalarda yoğun kullanımdan sonra bile) her zaman başarılı bir tahsis garantisi mi yoksa potansiyel olarak hala kilitlenecek mi?
Steven Lu

1
@Steven Lu cihazınıza bağlıdır. Örneğin, iPhone5 veya iPad4 gibi yeni olanlarda 70 Mb tahsisi hiç sorun değil.
Max

1
evet ama ben benim app toplam kullanım büyülü cihaza özel bellek bütçesinin altında sonlandırılmayacak tutmak sürece emin olabilirsiniz bilmek istiyorum!
Steven Lu

1
hiçbir garanti yoktur
Max

421

Split'in yazdığı yardımcı program ile test sonuçları (bağlantı cevabındadır):

cihaz: (kilitlenme miktarı / toplam miktar / toplamın yüzdesi)

  • iPad1: 127MB / 256MB /% 49
  • iPad2: 275MB / 512MB /% 53
  • iPad3: 645MB / 1024MB /% 62
  • iPad4: 585MB / 1024MB /% 57 (iOS 8.1)
  • iPad Mini 1.Nesil: 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, 1 TB):% 4598/5650/81 (iOS 12.1)
  • iPad 10.2: 1844/2998/62% (iOS 13.2.3)
  • iPod touch 4. nesil: 130MB / 256MB /% 51 (iOS 6.1.1)
  • iPod touch 5. nesil: 286MB / 512MB /% 56 (iOS 7.0)
  • iPhone4: 325MB / 512MB /% 63
  • iPhone4s: 286MB / 512MB /% 56
  • iPhone5: 645MB / 1024MB /% 62
  • iPhone5'ler: 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 Maks: 2067/3740/55 (iOS 13.2.3)

2
iPhone4: Benzer değer onaylandı, yasal görünüyor: P
cprcrack

3
iPhone 5 ± 645 MB'da kilitleniyor.
asp_net

4
@JasperPol Yayınınızı, sahip olduğum çeşitli cihazları içerecek şekilde düzenledim, umarım sorun olmaz. Önemli olması durumunda test ettiğim iOS sürümünü ekledim, ancak bunun önemli olmadığını düşünüyorsanız çekinmeyin.
JosephH

2
Bu listenin oluşturulmuş ve saklanmış olması harika. Deneyimlerime göre, güvenli olması için hafızayı çok daha düşük tutmalıydım, belki burada gösterilenlerin% 20'si. Cihazdan cihaza farklılıklar da oldukça değişkendir.
user1021430

1
Bunu 12.9 iPad Pro'da çalıştırdım. 2451MB'de bellek uyarısı, 3064MB'da kilitlenme, toplam 3981MB.
kilitleyin

134

Çökmek için olabildiğince fazla bellek ayırmaya çalışan küçük bir yardımcı program oluşturdum ve bellek uyarıları ve çökme meydana geldiğinde kaydediyor. Bu, herhangi bir iOS cihazı için bellek bütçesinin ne olduğunu bulmaya yardımcı olur.

https://github.com/Split82/iOSMemoryBudgetTest


İlginç bir test yaptım: xcode izleme bellek kullanımı ile uygulamamı çalıştırdım, arka plana girdim, BudgetTest'i çalıştırdım. Test, arka plandaki uygulamam olmadığında öldürüldü. Nedenini bilmekle ilgileniyorum. Ayrıca, bu diğer cevapta @cprcrack'ın söylediklerine aykırıdır.
Roberto

19

Uygulamamda, daha fazla bellek kullanılırsa kullanıcı deneyimi daha iyi, bu yüzden içinde kullanabileceğim tüm belleği boşaltmam gerekip gerekmediğine karar vermeliyimdidReceiveMemoryWarning . Split ve Jasper Pol'in cevabına dayanarak, toplam cihaz belleğinin maksimum% 45'ini kullanmak güvenli bir eşik gibi görünüyor (teşekkürler çocuklar).

Birisi benim gerçek uygulamama bakmak isterse:

#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 ( bu cevaba dayanarak ):

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
}

1
boyut sizeof (info) yerine TASK_BASIC_INFO_COUNT olmalıdır - bu hata aynı kodla birçok yere kopyalandı
Maxim Kholyavkin

Teşekkürler Speakus. Bu bağlantıya dayanarak haklı görünüyorsunuz . Bu bilgilerin bulunabileceği başka bir referansınız var mı?
cprcrack

elma kullandığı TASK_BASIC_INFO_COUNT çok
Maxim Kholyavkin

% 45 artık güvenli bir sınır değil, iPhone X için% 50 kilitlenme değerine çok yakın. Her cihaz için% 40 veya ayrı bir değer kullanmanızı öneririm.
Slyv

8

SPLITS repo'yu çatallayarak, Bugünün Uzantısına tahsis edilebilecek iOS belleğini test etmek için bir tane oluşturdum

iOSMemoryBudgetTestForExtension

IPhone 5s aldığım sonuç

10 MB'ta Bellek Uyarısı

Uygulama 12 MB'da Çöktü

Bu sayede Apple, yalnızca herhangi bir uzantının tam potansiyeliyle çalışmasına izin veriyor .


7

WWDC 2010 Oturum videolarından oturum 147'yi izlemelisiniz . "İPhone OS'de Gelişmiş Performans Optimizasyonu, bölüm 2" dir.
Bellek optimizasyonları hakkında birçok iyi tavsiye var.

Bazı ipuçları:

  • Yuvalanmış kullanın NSAutoReleasePoolBellek kullanımınızın artmadığından emin olmak için s .
  • CGImageSourceBüyük görüntülerden küçük resimler oluştururken kullanın .
  • Düşük bellek uyarılarına yanıt verin.

Sorum nasıl optimize edileceği ile ilgili değil (bağlantı için teşekkürler), kendimize ne kadar izin verebileceğimizle ilgili. Bunun nedeni, örneğin, 20mb kazanmak için optimize edersek, o zaman sanatçılar makul 20 bütçe dahilindeyse bu 20mb'yi kullanmak isteyeceklerdir, yani herhangi bir performans sorununa veya bellek çökmesine neden olmayacağından emin olabilirsiniz.
frilla

TAMAM. Çökme, işletim sisteminin kısıtlanmış bellek nedeniyle uygulamayı sonlandırması nedeniyle olacaktır. Sadece bir NSLogdidReceiveMemoryWarning
bölüm

4

İOS13'ten başlayarak, bunu kullanarak Apple tarafından desteklenen bir sorgulama yolu vardır

#include <os/proc.h>

size_t os_proc_available_memory(void)

Burada tanıtıldı: https://developer.apple.com/videos/play/wwdc2019/606/

Yaklaşık 29-ish.

Düzenleme: Dokümanlara bağlantı ekleme https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc


En sonunda! Birkaç cihazda os_proc_available_memory () test ettim ve sonuçlar yukarıdaki büyük tablo i değerlerine çok benzer!
Slyv

3
- (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;
}

Biri MACH_TASK_BASIC_INFO yerine TASK_BASIC_INFO_COUNT kullanırsa,

kerr == KERN_INVALID_ARGUMENT (4)


En azından cevabınızın @ cprcrack'ın neredeyse tam bir kopyası ve macunu olduğunu belirtmelisiniz . Tek fark TASK_BASIC_INFO_COUNT.
mrvincenzo

2

Jaspers listesini cihaz RAM'e göre sıralayarak bir liste daha oluşturdum (Split'in aracıyla kendi testlerimi yaptım ve bazı sonuçları düzelttim - Jaspers iş parçacığındaki yorumlarımı kontrol et).

cihaz RAM'i: çökme yüzdesi aralığı

  • 256 MB:% 49 -% 51
  • 512 MB:% 53 -% 63
  • 1024MB:% 57 -% 68
  • 2048MB:% 68 -% 69
  • 3072MB:% 63 -% 66
  • 4096 MB:% 77
  • 6144MB:% 81

Özel durumlar:

  • iPhone X (3072MB):% 50
  • iPhone XS / XS Maks (4096MB):% 55
  • iPhone XR (3072MB):% 63
  • iPhone 11/11 Pro Maks (4096 MB):% 54 -% 55

Cihaz RAM'i kolayca okunabilir:

[NSProcessInfo processInfo].physicalMemory

Deneyimlerime göre 1GB cihazlar için% 45, 2/3GB cihazlar için% 50 ve 4GB cihazlar için% 55 kullanmak güvenlidir. MacOS için yüzde biraz daha büyük olabilir.


güncelleme: iPhone X bir istisna gibi görünüyor - RAM'in% 50'si kullanıldığında çöküyor (iOSMemoryBudgetTest uygulaması ile test edildi). Listeyi güncelledim.
Slyv

0

Yukarıdaki birçok cevapla çalışırken, os_proc_available_memory()iOS 13+ için Apple'ın yeni yöntemini uyguladım ve bununla birlikte NSByteCountFormatterbelleğin daha iyi çıktısı için bir dizi yararlı biçimlendirme seçeneği sunuyor:

#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]);
    }
}

Önemli not: Sonunda unutmayın (). Yönteme her iki NSLogseçeneği de dahil ettim, memoryLoggingOutputçünkü eksik oldukları konusunda sizi uyarmaz ve parantezleri dahil edememek beklenmedik ama sabit bir sonuç döndürür.

Yöntemden döndürülen dize şöyle memoryStringForBytesdeğerler verir:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.