5

開発者向けドキュメントでは、次のように述べています。

アプリケーションまたはスレッドの寿命が長く、自動解放されたオブジェクトを大量に生成する可能性がある場合は、定期的に自動解放プールを排出して作成する必要があります (アプリケーション キットがメイン スレッドで行うように)。そうしないと、自動解放されたオブジェクトが蓄積され、メモリ フットプリントが大きくなります。ただし、切り離されたスレッドが Cocoa 呼び出しを行わない場合は、自動解放プールを作成する必要はありません。

これを行う最善の方法は何だろうと考えていました。うまくいくと思ういくつかの方法がありますが、どれが「最良」かわかりません。現在、スレッドを開始し、操作の実行を待機するメソッドがあります。

- (void)startThread
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    accessoryRunLoop = [NSRunLoop currentRunLoop];

    //Add a dummy port to avoid exiting the thread due to no ports being found
    [accessoryRunLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

    while(accessoryThreadIsRunning)
    {
        //Keep the thread running until accessoryTheadIsRunning == NO
        [accessoryRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }

    [pool release];
}

私が考えることができる私のオプションは次のとおりです。

1) while(accessoryThreadIsRunning) にカウンターを追加して、50 回または 100 回ごとに自動解放プールを空にし、新しいプールを作成します。

2) そのスレッドでメソッドを実行するたびに (performSelector: onThread: を使用)、自動解放プールを作成し、メソッドの最後でそれを解放できます。

3) プールが定期的に排出されてから作成されるようにタイマーを作成します。

オプション1が最適だと思いますが、これを行う別の方法があるかどうかを知りたいです。ありがとう!

4

4 に答える 4

4

私は非常に単純なものから始めて、ループを通過するたびにプールを作成/排出します。

パフォーマンス分析中にボトルネックとして表示された場合は、修正します。

複雑さが必要であることが分析で示されるまで、シンプルに保ちます。


私はあなたの質問を読み直して、私の答えに完全に頭がおかしいことに気づきました。実行ループを実行している場合は、自動解放プールを自動的に管理する必要があります。ループの上部にプールを作成し、ループを通過する各パスの最後にそれを排出する必要があります。

ランループの外で他のことが起こっている場合は、自分でサイクルする必要があるだけです。そうですか?

いずれにせよ、はい、パターンは次のとおりです。

 while(...) {
    ... create pool ...
    ... do stuff ...
    ... drain pool ...
 }
于 2010-09-27T19:38:59.763 に答える
2

毎回それを排出します。他の人が言っているように、自動解放プールを排水するのは安いです。

さらに、それを排出しないことは非常に費用がかかる可能性があります。自動リリースプールにページングを発生させるのに十分なものがある場合、ディスクI /Oが発生します。ディスクI/Oは、リリースを呼び出すリンクリストを実行するよりも文字通り数百万倍もコストがかかります。(そして、ページングがないiOSのようなシステムでは、自動解放を待機している余分なオブジェクトがたくさんあると、メモリ不足の警告が発生し、アプリケーションが強制的に終了したり、フォアグラウンドアプリケーションが大量のペン先ビューなどを解放したりする可能性があります、その後、後で再作成する必要があります...または、アプリケーションを強制的に終了させる場合があります)。

「十分な」余分なメモリを使用してメモリ不足の警告やページングを発生させない場合でも、排出するアイテムのリストが大きくなります。最新の自動リリースアイテムと最も古いアイテムの間で、より多くのメモリアクセスが行われます。最も古い自動リリースアイテムがメモリ階層内で遠くにある可能性がはるかに高いため、リリースでキャッシュミスが発生する可能性がありますが、L1またはL2キャッシュヒットが発生する可能性があります。したがって、おそらく100倍のコストがかかります。さらに、解放した(そしてキャッシュ内でホットだった可能性がある)メモリは、別のオブジェクトによって再利用された可能性があります。

したがって、50〜100回ごとに自動リリースを実行しても、時期尚早の最適化にはならない可能性があります。

ループごとに1つのリリースを実行し、それがボトルネックとして表示される場合は、X回ごとにリリースし、それによって速度が遅くなるのではなく速くなることを確認します。

于 2010-09-28T18:41:15.453 に答える
0

メインスレッドの実行ループはパスごとにプールを空にするので、他のスレッドでも実行するのが理にかなっています。プールを時々だけドレインすることを選択した場合、多くの自動解放されたオブジェクトが割り当て解除されるのを長時間待機するリスクがあります。実際、実行ループの各パスで解放できるメモリの量と、実行ループをトリガーする頻度によって異なります。簡単で、メモリフットプリントをできるだけ低く保つのに役立つという理由だけで、私は常に各パスでそれを排出することを好みます。

于 2010-09-27T20:11:36.283 に答える
0

従来の方法では、カウンターを保持し、50 回程度ごとにドレインしますが、bbum が言ったように、ループごとにプールをドレインすることから始めて、そこから先に進みます。または-init、自動解放されたオブジェクトを作成せずに、必要なオブジェクトを作成することもできます。(ファクトリメソッドは避けて-releaseください)ただし、すべてのオブジェクトを覚えておいてください。

于 2010-09-28T02:20:28.843 に答える