iOSアプリの最大メモリ量


152

私は少なくとも3gsをターゲットにしているiOSゲームに取り組んでいます。Retinaディスプレイデバイス(iphone 4、ipod touch第4世代)にHDアセットを使用しています。

メモリに関しては、Ipod Touch 4世代は3gsと同じ量のRAM(Iphone 4の512と比較して256)を持っているため、私たちにとって最も制約のあるデバイスのようですが、HDアセットを使用しています。以前は100〜110 MBのRAMを読み込もうとしたときにアプリがクラッシュしていましたが、70 MBに下がったため、読み込みがクラッシュすることはありませんでした。

多くの検索を行った後、公式のハードリミットはないようです。安全のために使用するメモリバジェットを知るにはどうすればよいでしょうか。私たちはアーティストに、各マップについてメモリの心配なしに使用できる予算を与えることができるようにしたいと考えています。



14
この質問が、後で質問されたものとどのように重複するのかはわかりません。
Jasper

回答:


42

私はあなたがあなた自身の質問に答えたと思います:70 Mbの制限を超えないようにしてください、しかしそれは実際には多くの事柄に依存します:使用しているiOSバージョン(SDKではない)、バックグラウンドで実行されているアプリケーションの数、正確なメモリあなたは等を使用しています

インスタントメモリのスプラッシュを回避するだけです(たとえば、40 MBのRAMを使用していて、短い計算のために80 MB以上を割り当てるなど)。この場合、iOSはアプリケーションをすぐに強制終了します。

アセットの遅延読み込みも検討する必要があります(事前にではなく、本当に必要な場合にのみ読み込みます)。


2
できる限り多くのもの(グラフィックとサウンド)を入れたかっただけです。アーティストは常にゲームにできるだけ多くのことを入れたいと思うので、予算で彼らを制限したいのです。使用する適切な最大メモリフットプリントを見つけるには、さまざまな設定のさまざまなデバイスでテストする必要があるだけだと思います。
frilla

2
そのデバイスでいつでも(おそらく予算を下回っている)70MBだけを割り当てると(他のメモリを大量に消費するアプリで大量に使用した後でも)、割り当ての成功が保証されますか、それとも潜在的にクラッシュしますか?
Steven Lu

1
@Steven Luそれはあなたのデバイスに依存します。たとえば、iPhone5やiPad4などの新しいものでは、70 Mbの割り当てはまったく問題ありません。
2013

1
はい。ただし、アプリの合計使用量が魔法のデバイス固有のメモリバジェットの下にある限り、アプリが終了しないことを確認できるかどうかを知りたいです。
Steven Lu

1
保証はありません
最大

421

ユーティリティSplitを使用したテストの結果は次のように書いています(リンクは彼の回答にあります)。

デバイス:(クラッシュ量/合計量/合計のパーセンテージ)

  • iPad1:127MB / 256MB / 49%
  • iPad2:275 MB / 512 MB / 53%
  • iPad3:645MB / 1024MB / 62%
  • iPad4:585MB / 1024MB / 57%(iOS 8.1)
  • iPad Mini第1世代:297MB / 512MB / 58%
  • iPad Mini Retina:696MB / 1024MB / 68%(iOS 7.1)
  • iPad Air:697 MB / 1024 MB / 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世代:130MB / 256MB / 51%(iOS 6.1.1)
  • iPod touch第5世代:286MB / 512MB / 56%(iOS 7.0)
  • iPhone4:325 MB / 512 MB / 63%
  • iPhone4s:286 MB / 512 MB / 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)

2
iPhone4:同様の値が確認され、正当なようです:P
cprcrack 2013年

3
iPhone 5は±645 MBでクラッシュします。
asp_net 2013

4
@JasperPol私が持っているさまざまなデバイスが含まれるようにあなたの投稿を編集しました。必要に応じて、テストしたiOSバージョンを追加しましたが、重要ではないと思われる場合は、遠慮なく削除してください。
JosephH 2014年

2
このリストが作成され、維持されていることは素晴らしいことです。私の経験では、安全のためにメモリをはるかに低く保つ必要がありました。ここに示されているもののおそらく20%です。デバイス間の違いも非常に変動します。
user1021430

1
これを12.9 iPad Proで実行しただけです。2451MBでのメモリ警告、3064MBでのクラッシュ、合計3981MB。
ロック

134

クラッシュにできるだけ多くのメモリを割り当てようとする小さなユーティリティを作成し、メモリ警告とクラッシュがいつ発生したかを記録しました。これは、iOSデバイスのメモリバジェットを確認するのに役立ちます。

https://github.com/Split82/iOSMemoryBudgetTest


私は興味深いテストを行いました。メモリ使用量を監視するxcodeでアプリを実行し、バックグラウンドに入り、BudgetTestを実行しました。私のバックグラウンドアプリがそうでなかった間に、テストは殺されました。なぜか知りたいです。また、これは、@ cprcrackが他の回答で言ったことに反します。
ロベルト

19

私のアプリでは、より多くのメモリを使用する方がユーザーエクスペリエンスが向上するので、実際にできるすべてのメモリを解放する必要があるかどうかを判断する必要がありdidReceiveMemoryWarningます。スプリットとジャスパーポールの回答に基づいて、合計デバイスメモリの最大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
}

1
サイズはsizeof(info)ではなくTASK_BASIC_INFO_COUNTにする必要があります-この間違いは同じコードで多くの場所にコピー
アンド

スピークスに感謝します。あなたはこのリンクに基づいて正しいようです。この情報を見つけることができる他の参照がありますか?
cprcrack 2013

アップル
Maxim Kholyavkin

45%はもはや安全な制限ではなく、iPhone Xのクラッシュ値の50%に近すぎます。デバイスごとに40%または個別の値を使用することをお勧めします。
Slyv

8

SPLITSリポジトリをフォークすることで、Today's Extensionに割り当てることができるiOSメモリをテストするためにリポジトリを構築しました

iOSMemoryBudgetTestForExtension

以下はiPhone 5sで得た結果です

10 MBでのメモリ警告

アプリが12 MBでクラッシュした

これは、Appleが拡張機能を最大限に活用できるようにすることを意味しています。


7

WWDC 2010セッションビデオのセッション147をご覧ください。「iPhone OSでの高度なパフォーマンス最適化、パート2」です。
メモリの最適化については、たくさんの良いアドバイスがあります。

ヒントは次のとおりです。

  • ネストされたをNSAutoReleasePool使用して、メモリ使用量が急増しないようにします。
  • CGImageSource大きな画像からサムネイルを作成するときに使用します。
  • メモリ不足の警告に応答します。

私の質問は、最適化の方法(リンクのおかげであります)についてではなく、自分がどれだけ使用できるかについてです。その理由は、たとえば、20 mbを獲得するように最適化した場合、アーティストはその20 mbが妥当な「予算」内であれば、その20 mbを使用することになるため、パフォーマンスの問題やメモリクラッシュが発生しないことを確認してください。
frilla

OK。クラッシュの原因は、メモリの制約によりOSがアプリを終了していることです。あなただけ追加することができますNSLog内側にdidReceiveMemoryWarningして、あなたはメモリの異なる量を割り当てるいくつかのテストを行い、その後、メモリの警告がでキックを開始したときに参照してください。
Kobski

4

iOS13以降では、Appleがサポートする方法を使用してこれを照会する方法があります

#include <os/proc.h>

size_t os_proc_available_memory(void)

ここに導入:https : //developer.apple.com/videos/play/wwdc2019/606/

29分くらい。

編集:ドキュメントへのリンクを追加 https://developer.apple.com/documentation/os/3191911-os_proc_available_memory?language=objc


最後に!いくつかのデバイスでos_proc_available_memory()をテストしましたが、結果は上記の大きなテーブルの値と非常によく似ています!
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;
}

MACH_TASK_BASIC_INFOの代わりにTASK_BASIC_INFO_COUNTを使用すると、次のようになります。

kerr == KERN_INVALID_ARGUMENT(4)


少なくとも、あなたの答えは上記の@cprcrackのほぼ正確なコピー&ペーストであることを言及する必要があります。唯一の違いはTASK_BASIC_INFO_COUNTです。
mrvincenzo

2

JaspersリストをデバイスRAMでソートして、もう1つリストを作成しました(Splitのツールで独自のテストを行い、結果をいくつか修正しました-Jaspersスレッドでコメントを確認してください)。

デバイスRAM:クラッシュする範囲のパーセント

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

特殊なケース:

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

デバイスRAMは簡単に読み取ることができます。

[NSProcessInfo processInfo].physicalMemory

私の経験から、1GBデバイスでは45%、2 / 3GBデバイスでは50%、4GBデバイスでは55%を使用しても安全です。macOSの割合は少し大きくなることがあります。


更新:iPhone Xは例外のようです-RAMの50%が使用されるとクラッシュします(iOSMemoryBudgetTestアプリでテスト済み)。リストを更新しました。
Slyv

0

上記の多くの答えに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]);
    }
}

重要な注意:最後にを忘れないでください()両方のNSLogオプションがmemoryLoggingOutputメソッドに含まれているのは、これらのオプションが欠落していることを警告せず、ブラケットを含めないと予期しない一定の結果が返されるためです。

メソッドから返された文字列は、次の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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.