web-dev-qa-db-ja.com

iPhoneのメモリ消費量を理解する

OpenGLESを使用して2DiPhoneゲームに取り組んでいますが、24 MBのメモリ制限に達し続けています。アプリケーションがエラーコード101でクラッシュし続けます。メモリの場所を見つけるために一生懸命努力しましたが、Instrumentsの数値はまだたくさんあります予想よりも大きいです。

メモリモニター、オブジェクト割り当て、リーク、OpenGLES機器を使用してアプリケーションを実行しました。アプリケーションが読み込まれると、空き物理メモリが37MBから23MBに減少し、オブジェクト割り当てが約7 MBに落ち着き、リークは数バイトのサイズで2つまたは3つのリークを示し、Gartオブジェクトサイズは約5 MBであり、メモリモニターはアプリケーションは約14MBの実メモリを占有します。私はメモリがどこに行ったのか戸惑っています。オブジェクトの割り当てを掘り下げたとき、メモリのほとんどは、私が期待するとおりにテクスチャにあります。しかし、私自身のテクスチャ割り当てカウンターとGart Object Sizeの両方が、テクスチャが約5MBを占める必要があることに同意しています。

私は言及する価値のある他のものを割り当てることに気づいていません、そしてオブジェクト割り当ては同意します。記憶はどこに行きますか? (これで十分でない場合は、詳細をお知らせいただければ幸いです。)


更新:本当に多くのメモリを割り当てることができる場所を見つけようとしましたが、結果はありませんでした。私を夢中にさせるのは、メモリモニター(〜14 MB)で示されるように、オブジェクトの割り当て(〜7 MB)と実際のメモリ使用量の違いです。忘れてしまった大量のリークや大量のメモリがあったとしても、はオブジェクト割り当てに表示されるはずですよね?

私はすでに 通常容疑者 を試しました。 UIImageとそのキャッシュがありますが、それは役に立ちませんでした。各ステートメントがメモリ使用量に与える影響を監視しながら、メモリ使用量を「デバッガスタイル」で1行ずつ追跡する方法はありますか?


これまでに見つけたもの:

  1. 私は本当にamそれだけのメモリを使用しています。実際のメモリ消費量を測定するのは簡単ではありませんが、多くのカウントを行った後、メモリ消費量は本当に非常に高いと思います。私のせい。

  2. 使用したメモリを測定する簡単な方法が見つかりませんでした。メモリモニターの数値は正確ですが(これらは本当に重要な数値です)、メモリモニターはメモリの正確な場所を教えてくれません。 Object Allocツールは、実際のメモリ使用量を追跡するのにほとんど役に立ちません。テクスチャを作成すると、割り当てられたメモリカウンタがしばらく上昇し(テクスチャをメモリに読み込む)、その後低下します(テクスチャデータをOpenGLに渡して解放します)。これは問題ありませんが、常に発生するとは限りません。テクスチャがOpenGLに渡され、「マイ」メモリから解放された後でも、メモリ使用量が高いままである場合があります。これは、Object Allocツールによって示されるように割り当てられたメモリの合計量は、実際の合計メモリ消費量よりも少ないが、実際の消費量からテクスチャを差し引いたものよりも多いことを意味します(real – textures < object alloc < real)。図に行きます。

  3. プログラミングガイドを読み間違えました。 24 MBのメモリ制限は、アプリケーション全体ではなく、テクスチャとサーフェスに適用されます。実際の赤い線はもう少し先にありますが、難しい数字は見つかりませんでした。コンセンサスは、25〜30MBが上限であるということです。

  4. システムのメモリが不足すると、メモリ警告の送信が開始されます。解放するものはほとんどありませんが、他のアプリケーション、特にSafari(Webサイトをキャッシュしているようです)は、システムにメモリを解放します。メモリモニターに表示される空きメモリがゼロになると、システムは強制終了を開始します。

メモリをより効率的にするために、弾丸を噛んでコードの一部を書き直さなければなりませんでしたが、おそらくまだそれを推し進めています。別のゲームを設計する場合は、確かにリソースのページングについて考えます。現在のゲームでは、物事は常に動いていて、別のスレッドで行われたとしても、テクスチャの読み込みが邪魔になるため、非常に困難です。 他の人がこの問題をどのように解決するかに非常に興味があります。

これらは私の見解であり、それほど正確である必要はないことに注意してください。このトピックについてさらに言いたいことがあれば、質問を更新します。問題を理解している人が答えてくれる場合に備えて、質問は開いたままにしておきます。これらはすべて、他の何よりも回避策と推測であるためです。

35
zoul

これがInstrumentsのバグだとはとても疑わしいです。

まず、これを読んでください openGLテクスチャに関するJeff Lamarcheによるブログ投稿

  • リークを発生させずにテクスチャをロードする方法の簡単な例があります
  • 「小さな」画像がどのようにopenGLにロードされたら取得し、実際に「大量の」メモリを使用するかを理解できます

抜粋:

テクスチャは、圧縮された画像から作成されている場合でも、使用するにはメモリ内で拡張する必要があるため、アプリケーションのメモリヒープを大量に使用します。すべてのピクセルは4バイトを占めるため、テクスチャ画像データの解放を忘れると、メモリがすぐに消費される可能性があります。

次に、Instrumentsを使用してテクスチャメモリをデバッグすることができます。 2つのプロファイリング構成があります: OpenGL ESアナライザー および OpenGL ESドライバー 。シミュレーターはOpenGLを使用しないため、これらをデバイスで実行する必要があります。 XCodeからProduct-> Profileを選択し、Instrumentsが起動したらこれらのプロファイルを探すだけです。


その知識を武器に、これが私がすることです:

  • あなたがそうでないことを確認してください メモリリーク -これは明らかにこの問題を引き起こします。
  • 'eが 自動解放されたメモリへのアクセス -クラッシュの一般的な原因ではないことを確認してください。
  • 別のテストアプリを作成し、テクスチャを個別に(および組み合わせて)ロードして、問題の原因となっているテクスチャ(またはその組み合わせ)を見つけます。

UPDATE:あなたの質問について考えた後、私は読んでいます AppleのOpenGL ESプログラミングガイド そしてそれは非常に良い情報を持っています。強くお勧めします!

11
bentford

1つの方法は、コードをコメントアウトし、バグがまだ発生するかどうかを確認することです。はい、それは退屈で初歩的なものですが、バグがどこにあるかを知っていれば役立つかもしれません。

クラッシュしているのは、クラッシュしている理由などです。

3
Genericrich

うーん、それは多くの詳細ではありませんが、リークがリークの場所を示していない場合は、2つの重要なオプションがあります。

[i]リークがリークを見逃した[ii]メモリが実際にリークされていない

[i]の修正は非常に困難ですが、Eric Albertが言ったように、バグレポートをAppleで提出すると役立ちます。[ii]は、使用しているメモリがまだどこかでアクセス可能であることを意味しますが、おそらくあなたは'それを忘れてしまいました。古いエントリを破棄せずにリストが増えていますか?バッファが大量にrealloc()されていますか?

2
user23743

2012年以降にこれを見た人のために:

デバイスの物理メモリに実際にロードされるメモリは、VM TrackerInstrumentの常駐メモリです。

Allocation Instrumentは、malloc/[NSObject alloc]によって作成されたメモリのみをマークし、一部のフレームワークバッファ、たとえば、解凍された画像ビットマップはAllocation Instrumentに含まれませんが、常にほとんどのメモリを消費します。

Appleから情報を入手するには、WWDC2012セッション242iOSアプリのパフォーマンス:メモリをご覧ください。

2
CarmeloS

これは特に役に立ちませんが、メモリツールが必要なすべてのデータを提供しない場合は、bugreport.Apple.comでバグを報告してください。アプリのコピーと、ツールが分析にどのように不足しているかの説明を添付してください。Appleは、ツールを改善できるかどうかを確認します。ありがとうございます。

0
Eric Albert