ここでの問題は、 で「ビジー待機」していることです。adaptor.assetWriterInput.readyForMoreMediaData
つまり、タイトなループで何度も呼び出しています。これは、一般的に言えば、悪い習慣です。ヘッダーには、このプロパティは Key-Value Observable であると記載されているため、プロセス全体を進めるために、Key-Value 変更通知をリッスンするようにコードを再構築することをお勧めします。さらに悪いことに、AVAssetInputWriter
動作方法によっては (実行ループ ベースかどうかはわかりません)、ここでのビジー待機の行為により、アセット入力ライターが実際の作業を実行できなくなる可能性があります。実行ループを続行させるまで発生しない可能性のある作業が行われるのを待っているデッドロック。
今、あなたは自問しているかもしれません: ビジー待機はどのようにメモリ プレッシャを引き起こしているのでしょうか? 舞台裏で、readyForMoreMediaData
呼び出すたびに自動解放されたオブジェクトが割り当てられるため、メモリ不足が発生しています。この値をビジー待機してタイトなループで何度もチェックするため、実行ループが自動解放プールをポップする機会がないため、ますます多くのオブジェクトが割り当てられ、解放されることはありません。(実際の割り当ての詳細については、以下を参照してください) この (不適切な) ビジー待機を継続したい場合は、次のようにしてメモリの問題を軽減できます。
BOOL ready = NO;
do {
@autoreleasepool {
ready = adaptor.assetWriterInput.readyForMoreMediaData;
}
} while (!ready);
これにより、によって作成された自動解放されたオブジェクトはreadyForMoreMediaData
、各チェックの後に解放されます。しかし、実際には、このコードを再構築してビジー待機を回避することで、長期的にははるかに優れたサービスを提供できます。絶対にビジーウェイトが必要な場合は、少なくともループの各パスで次のようなことを行うと、CPUをusleep(500);
それほどスラッシングしなくなります。しかし、忙しくしないでください-待ってください。
編集:Instrumentsからこれを理解する方法を理解したいと思っていたこともわかりました。説明してみましょう。あなたが投稿したファイルから始めて、私がしたことは次のとおりです。
上部ペインの [割り当て] 行をクリックしてから、[作成済み & まだ生きている] オプションを選択しました (オブジェクトが破壊されている場合、ヒープの成長は見られないためです)。次に、[オプション] で時間フィルターを適用しました。表示されている大きな「ランプ」で小さな範囲をドラッグします。この時点で、ウィンドウは次のようになります。
ここで、非常によく似た 4K の malloc されたオブジェクトがリストにたくさんあることがわかります。これが喫煙銃です。次に、それらのいずれかを選択し、ウィンドウの右側のペインを展開してスタック トレースを表示します。この時点で、ウィンドウは次のようになります。
右側のパネルに、そのオブジェクトが作成されているスタック トレースが表示されます。これは で割り当てられていることがわかりAVAssetInputWriter
ますが、コードの最後のフレームの下 (視覚的には上) にある最初の関数は です-[AVAssetWriterInput isReadForMoreMediaData]
。バックトレースには、これが自動解放されたオブジェクトに関連しているというヒントがあり、そのautorelease
ようなタイトなループに座っていると、標準の自動解放メカニズムが実行される機会がありません (つまり、現在のプールがポップされます)。
このスタックからの私の結論は、-[AVAssetWriterInput isReadForMoreMediaData]
, (おそらく_helper
次のスタック フレーム内の関数) 内の何かが、[[foo retain] autorelease]
結果を返す前に a を実行するということです。自動解放メカニズムは、自動解放プールがポップ/ドレインされるまで、自動解放されたすべてのものを追跡する必要があります。それらを追跡するために、「自動解放されるのを待っているもののリスト」にスペースを割り当てる必要があります。これは、これらが malloc ブロックであり、自動解放されたオブジェクトではない理由についての私の推測です。(つまり、割り当てられているオブジェクトはありませんが、プールがプッシュされてから発生したすべての自動解放操作を追跡するためのスペースだけがあります。このプロパティをタイトなループでチェックしているため、そのうちの多くがあります。 )
それが私が問題を診断した方法です。うまくいけば、それは将来あなたを助けるでしょう。