11

Apples のドキュメントのほとんどは、特に GUI ビューを作成するときに、自動解放されたオブジェクトの使用を避けているようですが、自動解放されたオブジェクトを使用するコストを知りたいですか?

UIScrollView *timeline = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 20, 320, 34)];
[self addSubview:timeline];
[timeline release];

最終的に、すべてが自動解放され、retain/release の使用が特定のケースのルールの例外となる戦略を使用する必要がありますか? または、 [NSString stringWithEtc...] のような便利なメソッドから返されたオブジェクトの例外である autorelease を使用して、一般的に保持/解放を使用する必要がありますか?

4

11 に答える 11

21

2 つのコストがあります。

  1. (自動解放されたオブジェクトを回避するオプションがあると仮定します。)オブジェクトの有効期間を事実上不必要に延長します。これは、メモリ使用量が不必要に増加することを意味します。制約のあるプラットフォームでは、制限を超えるとアプリケーションが終了する可能性があります。制限を超えていない場合でも、システムがスワッピングを開始する可能性があり、これは非常に非効率的です。

  2. 現在の自動解放プールを見つけ、そこに自動解放されたオブジェクトを追加し、最後にオブジェクトを解放する (追加のメソッド呼び出し) という追加のオーバーヘッド。これは大きなオーバーヘッドではないかもしれませんが、追加される可能性があります。

あらゆるプラットフォームでのベスト プラクティスは、可能であれば自動解放を回避することです。

質問に答えるには:

最終的に、すべてが自動解放され、retain/release の使用が特定のケースのルールの例外となる戦略を使用する必要がありますか?

まったく逆です。

または、 [NSString stringWithEtc...] のような便利なメソッドから返されたオブジェクトの例外である autorelease を使用して、一般的に保持/解放を使用する必要がありますか?

可能であれば、常に保持/解放を使用する必要があります。同等のメソッドがあるため、通常、メソッドNSStringを使用する必要はありません。stringWithEtcinitWithEtc

この質問も参照してください。

于 2008-10-11T04:23:37.030 に答える
15

Jim Puls の意見には同意できません。Autorelease を使用しないと、デバッグがより困難になると思います。誤ってメモリ リークが発生する可能性が高くなるからです。もちろん、Clang 静的アナライザーはこれらのインスタンスのいくつかを拾うことができますが、私にとっては、autorelease を習慣的に使用することによるわずかなオーバーヘッド コストは、バグが発生する可能性が低いコードによってはるかに影が薄くなります。

そして、最適化する必要があるタイトなループがある場合にのみ、パフォーマンスに注目します。それ以外の場合、これはすべて時期尚早の最適化であり、一般に悪いことと見なされます。

于 2008-10-12T16:23:40.353 に答える
9

まだ誰もこれについて言及していないことに驚いています。パフォーマンスとは何の関係もない場合に自動解放されたオブジェクトを避ける最大の理由。はい、ここで言及されているパフォーマンスの問題はすべて完全に有効ですが、自動解放の最大の欠点は、デバッグが非常に困難になることです。

自動解放されないオーバーリリースされたオブジェクトがある場合、追跡するのは簡単です。NSPopAutoreleasePool の南のどこかでバックトレースが断続的に発生するクラッシュがユーザーから報告された場合は、頑張ってください...

于 2008-10-11T07:42:29.830 に答える
8

私は一般的に自動解放されたオブジェクトを最近使用しています。これは、コードがよりシンプルで読みやすいものになる傾向があるためです。それらを宣言して初期化し、スコープから除外します。機械的にはかなり長く存在しますが、コードを書いている人の観点からは、C++ でスタック宣言されたオブジェクトが、関数が返されてそのフレームが破棄されると自動的に破棄されるのと同じです。

効率の低下はありますが、ほとんどの場合、それは重要ではありません。より大きな問題は、より多くのオブジェクトが存在し、後でメモリを回復すると、アドレス空間がより断片化される可能性があることです。それが問題である場合は、通常、いくつかのホットな方法で手動の保持/解放に切り替えて改善するのはかなり簡単です。

他の人が言ったように、可読性は、パフォーマンスに影響されないコードのパフォーマンスよりも優先されます。自動解放されたオブジェクトを使用すると、より多くのメモリの断片化が発生するケースが多数ありますが、オブジェクトがプールを超えて存続する場合は、そうではありません。そのような場合、あなたが支払う唯一の代償は、正しい自動解放プールを見つけるためのコストを見つけることです。

于 2008-10-22T19:47:33.383 に答える
7

自動解放プールを使用する利点の 1つは、 @try/を使用しなくても例外セーフであること@finallyです。Greg Parker (「Mr. Objective-C」) は、この詳細を説明する素晴らしい投稿をしています。

私はより少ないコードとして多くを使用する傾向がありautorelease、IMO をより読みやすくします。他の人が指摘しているように、マイナス面は、オブジェクトの寿命を延ばすことで、一時的により多くのメモリを使用することです。実際には、私autoreleaseが書いた Mac アプリの中で、 の使いすぎが重大な問題であるとはまだ思っていません。高いメモリ使用量が問題であると思われる場合 (それは本物のリークが原因ではありません)、自動解放プールを追加するだけです (プロファイリングを行って必要な場所を示した後)。しかし、一般的に、これは非常にまれです。Mike Ash の投稿 (Graham Lee リンク) が示すように、自動解放プールはオーバーヘッドがほとんどなく、高速です。自動解放プールを追加するコストはほぼゼロです。

確かに、これはすべて Mac アプリ用です。メモリがより逼迫している iPhone アプリでは、autorelease の使用を控えた方がよい場合があります。ただし、いつものように、最初に読み取り可能なコードを記述し、後で低速/メモリ集約型の部分を測定して最適化します。

于 2008-10-22T04:57:44.413 に答える
6

費用は次のとおりです。

  1. 現在のスレッドの自動解放プールを見つけて、それにオブジェクトを追加する時間。
  2. 後で解放されるまで、オブジェクトによって占有されていたメモリ。

メモリ使用量を非常に控えめにしたい場合は、自動解放を避ける必要があります。ただし、これはコードを読みやすくする便利な手法です。執拗に保持/解放を使用することは、「時期尚早の最適化」の範疇に入ります。

Cocoa のメイン イベント処理スレッド (ほとんどの場合) を使用している場合、制御がイベント ハンドラーに戻ると自動解放プールは空になります。メソッドが短く、大量のデータをループしない場合は、autorelease を使用して割り当て解除を実行ループの最後まで延期しても問題ありません。

ループに陥ったときは、自動解放に注意する必要があります。たとえば、ユーザーのアドレス帳を反復処理し、おそらく各エントリの画像ファイルをロードしています。これらの画像オブジェクトがすべて自動解放されている場合、アドレス帳全体にアクセスするまで、それらはメモリに蓄積されます。アドレス帳が十分に大きい場合、メモリが不足する可能性があります。画像の処理が完了したらすぐに解放すると、ループ内でアプリがメモリをリサイクルできます。

ループ内での自動解放を避けることができない場合 (それは、記述していない変更できないコードによって行われている場合)、必要に応じてループ内で NSAutoreleasePool を管理することもできます。

そのため、ループ (またはループから呼び出される可能性のあるメソッド) 内で autorelease を使用することに注意してください。ただし、コードが読みやすくなる場合は避けないでください。

于 2008-10-11T07:36:09.887 に答える
2

自動解放すべきかどうかについて他の人が回答していますが、自動解放が必要な場合は、早期に排出し、頻繁に排出してください: http://www.mikeash.com/?page=pyblog/autorelease-is-fast.html

于 2008-10-12T13:10:23.583 に答える
2

私が理解しているように、autorelease を使用することの主な欠点は、オブジェクトが最終的にいつ解放されて破棄されるかわからないことです。これにより、自動解放されたがまだ解放されていないオブジェクトがたくさんある場合、アプリが必要以上に多くのメモリを使用する可能性があります。

于 2008-10-10T23:44:40.683 に答える
1

提供されたコード サンプルは iPhone 用であることがわかりました。Apple は、iPhone アプリの自動解放オブジェクトを避けることを特に推奨しています。具体的な理由はわかりませんが、彼らは WWDC でこの点を強調していました。

于 2008-10-15T14:17:00.153 に答える
0

古いスレッドですが、新しい読者の利益のために欠けています。

オブジェクトに固有の自動リリースのバグのリスクとオブジェクトのサイズに応じて、自動リリースと保持/リリースを使用します。いくつかの小さなUIImageViewまたはいくつかのUILabelをビューに追加するだけの場合、自動リリースによりコードが読みやすく管理しやすくなります。また、ビューが削除されて割り当てが解除されると、これらのサブビューはすぐに解放されるはずです。

一方、UIWebView(自動リリースのバグのリスクが高い)、またはもちろんオブジェクトの「死」まで永続化する必要のあるデータについて話している場合は、保持/リリースが最適です。

正直なところ、私のプロジェクトはまだそれほど大きくはなっておらず、自動解放されたオブジェクトの追加の「滞在時間」によってメモリの問題が発生します。複雑なアプリの場合、その懸念は正当です。

いずれにせよ、万能のアプローチは正しいとは思いません。上記のすべての要素を念頭に置いて、プロジェクトに適したアプローチ(またはアプローチの組み合わせ)を使用します。

于 2010-03-30T15:53:57.540 に答える
0

覚えておくべき 1 つの注意点は、新しいスレッドを生成する場合は、他のことを行う前に、そのスレッドに新しい Autorelease プールをセットアップする必要があるということです。autorelease オブジェクトを使用していない場合でも、Cocoa API の何かがそうである可能性があります。

于 2008-10-15T13:57:17.043 に答える