web-dev-qa-db-ja.com

高レベルのアプリケーションでは、NSOperationおよびブロックよりもGCDを選択する必要があるのはなぜですか?

AppleのGrand Central Dispatchリファレンスは次のように述べています。

"...アプリケーションがシステムのUnixレベルで動作する必要がある場合—たとえば、ファイル記述子、マッハポート、信号、またはタイマーを操作する必要がある場合。GCDはシステムレベルのアプリケーションに限定されませんが、上位レベルのアプリケーションに使用する場合は、Cocoaで提供されている同様の機能(NSOperationおよびブロックオブジェクトを介して)が使いやすいか、ニーズにより適しているかを検討する必要があります。

http://developer.Apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

GCDの使用が必須であり、NSOperationを使用することができる/すべきではない、高レベルのアプリケーションの状況を実際に考えることはできません。

何かご意見は?

33
Lio

ここで行われている点は、Chris Hansonが彼の記事で述べている「 NSOperationとGCDを使用する場合 」と同じです。

簡単な答えは、すべてのアプリケーション開発の一般的なガイドラインです。

常に使用可能な最高レベルの抽象化を使用し、測定によりそれらが必要であることが示された場合は、より低いレベルの抽象化にドロップダウンしてください。

この特定のケースでは、Cocoaアプリケーションを作成するときは、通常、GCDを直接使用するのではなく、NSOperationを使用する必要があります。効率の違いのためではなく、NSOperationがGCDのメカニズムの上に高レベルの抽象化を提供するためです。

一般的に、私はこれに同意します。 NSOperationとNSOperationQueueは、GCDブロックとキューにはない依存関係と1つまたは2つのその他のものをサポートし、並行操作の実装方法の下位レベルの詳細を抽象化します。その機能が必要な場合、NSOperationは非常に良い方法です。

ただし、両方で作業した後、NSOperationベースのコードをすべてGCDブロックとキューで置き換えていることに気付きました。私がこれを行った理由は2つあります。NSOperationを頻繁なアクションに使用するとかなりのオーバーヘッドが発生することと、GCDブロックを使用するとコードがより簡潔でわかりやすくなると思います。

最初の理由は、アプリケーションでのプロファイリングにあります。そこでは、OpenGL ESフレームを画面にレンダリングするなど、小さくて頻繁なアクションを処理するときに、NSOperationオブジェクトの割り当てと割り当て解除のプロセスがかなりの量のCPUリソースを消費することがわかりました。 GCDブロックはそのオーバーヘッドを完全に排除し、パフォーマンスを大幅に向上させました。

2番目の理由は主観的ですが、NSOperationsよりもブロックを使用する方が私のコードはよりクリーンだと思います。ブロックによって許可されたスコープの迅速なキャプチャとそれらのインラインの性質により、カスタムのNSOperationサブクラスを作成したり、操作に渡されるパラメーターをバンドルしたりする必要がないため、コードが少なくなり、私の意見ではより記述的なコードになります。実行されるコードは、実行されるポイントのキューに配置できるためです。

繰り返しますが、それは好みの問題ですが、より抽象化されたCocoaアプリケーションでも、GCDをより多く使用していることに気づきました。

55
Brad Larson
  • タスクがそれほど複雑ではなく、最適なCPUパフォーマンスが必要なGCDを優先します。
  • タスクが複雑で、ブロックのキャンセルまたは一時停止と依存関係の管理が必要なNSOperationQueueを優先します

GCDは、同時に実行される作業単位を表す軽量な方法です。これらの作業単位はスケジュールしません。システムがスケジュールを管理します。ブロック間の依存関係を追加すると、頭痛の種になる可能性があります。ブロックをキャンセルまたは一時停止すると、開発者として余分な作業が発生します。

NSOperationとNSOperationQueueは、GCDと比較して少し余分なオーバーヘッドを追加しますが、さまざまな操作間の依存関係を追加できます。操作は再利用、キャンセル、または一時停止できます。 NSOperationはKey-Value Observation(KVO)と互換性があります。たとえば、NSNotificationCenterをリッスンすることで、NSOperationの実行を開始できます。

詳細な説明については、この質問を参照してください: NSOperation vs Grand Central Dispatch

13
Nitesh Borad

NSOperationには、dispatch_source_t、dispatch_io、dispatch_data_t、dispatch_semaphore_tなどに相当するものはありません。オーバーヘッドも多少高くなります。

反対に、libdispatchには、操作の依存関係、操作の優先度(キューの優先度は多少異なります)、または操作に対するKVOに相当するものはありません。

4
Catfish_Man

NSOperationQueueがGCDで実行できないことには、2つの機能があります。マイナーなものは依存関係(操作をキューに追加するが、他の特定の操作が終了したときにのみ実行するように指示する)と、大きなものはNSOperationによって提供されることです非常に限られた方法を除いてメッセージを受信できないブロックを持つGCDとは異なり、タスクの実行中にメッセージを受信できるオブジェクト。これらの2つの機能が必要か、必要ではありません。そうでない場合、GCDを使用するのは非常に簡単です。

そのため、NSOperationの有用な例は常に非常に複雑です。簡単であれば、代わりにGCDを使用します。通常、NSOperationのサブクラスを作成しますが、これはかなりの量の作業になるか、他の誰かが作成したものを使用します。

1
gnasher729

私は実際に「これについてのラウンドを読んでいます、そして、私はそれが驚きを知っているように来ると確信しています、意見は異なります。

NSOperationではなくGCDを使用する必要があるケースは考えられませんが、そのようなケースが存在しないという意味ではありません。ただし、ベストプラクティスのコーディングに関する一般的な意見には同意します。

仕事に適したツールがいくつかある場合(この場合、NSOperationとGCDブロックがある場合)、抽象化のレベルが最も高いクラス(つまり、最もレベルの高いAPI)を使用します。通常はコードが使いやすく/コードが少ないだけでなく、より高レベルのAPIに導入された潜在的な将来の拡張機能からも利益を得られます。

0
isaac