私はiOS用の並行プログラミングについて学んでいます。これまで NSOperation
/NSOperationQueue
と GCD
について読みました。 NSOperationQueue
よりGCD
を使用する理由は何ですか?
GCD
とNSOperationQueue
の両方が、ユーザーからのNSThreads
の明示的な作成を抽象化しているように聞こえます。しかし、2つのアプローチの関係は私には明らかではないので、フィードバックをいただければ幸いです。
GCD
は、タスクベースの並行性モデルを非常に簡単に使用できるようにする低レベルのCベースのAPIです。 NSOperation
とNSOperationQueue
は同様のことをするObjective-Cのクラスです。 NSOperation
が最初に導入されましたが、10.6とiOS 4以降、NSOperationQueue
とその仲間はGCD
を使って内部的に実装されています。
一般に、あなたはあなたのニーズに合った最高レベルの抽象化を使うべきです。これは、NSOperationQueue
がサポートしていないことをする必要がない限り、通常はGCD
の代わりにNSOperationQueue
を使うべきであることを意味します。
NSOperationQueue
はGCDの "卑劣な"バージョンではないことに注意してください。実際、NSOperationQueue
を使って非常に単純にできることは、純粋なGCD
を使って多くの作業を必要とすることがたくさんあります。 (例:一度にN個のオペレーションのみを実行する帯域幅制限キュー、オペレーション間の依存関係の確立。両方ともNSOperation
では非常に単純、GCD
では非常に困難です。)AppleはGCDを利用してとてもいいオブジェクトフレンドリAPIを作成するという大変な作業を行いました。 NSOperation
と一緒に。あなたがしない理由がない限り、彼らの仕事を利用してください。
警告:一方、本当にブロックを送信する必要があるだけで、NSOperationQueue
が提供する追加機能を必要としない場合は、 GCDを使用しても問題ありません。それが仕事に適したツールであることを確認してください。
関連する質問に対する私の答え に沿って、私はBJに反対し、最初にGCD over NSOperation/NSOperationQueueをご覧になることをお勧めします。後者は、GCDが必要としないものを提供します。
GCDが登場する前は、並行性を管理するために、アプリケーション内で多数のNSOperations/NSOperationQueuesを使用していました。しかし、私は定期的にGCDを使い始めてから、NSOperationsとNSOperationQueuesをブロックとディスパッチキューに完全に置き換えました。これは、両方のテクノロジを実際に使用した方法と、それらを実行したプロファイリングからきたものです。
まず、NSOperationsとNSOperationQueuesを使用する場合、重要なオーバーヘッドがあります。これらはCocoaオブジェクトなので、割り当てと割り当て解除を行う必要があります。私が書いたiOSアプリケーションでは、60 FPSで3Dシーンをレンダリングしていましたが、レンダリングされた各フレームをカプセル化するためにNSOperationsを使用していました。私がこれをプロファイルしたとき、これらのNSOperationsの作成と破棄は実行中のアプリケーションのCPUサイクルのかなりの部分を占めていて、物事を遅くしていました。これらを単純なブロックとGCDシリアルキューに置き換えたところ、オーバーヘッドがなくなり、レンダリングパフォーマンスが著しく向上しました。これが私がNSOperationsの使用によるオーバーヘッドに気付いた唯一の場所ではなく、私はこれをMacとiOSの両方で見ました。
第二に、NSOperationsを使用するときに一致するのが難しいブロックベースのディスパッチコードへの優雅さがあります。数行のコードをブロックでラップし、それをシリアルまたは並行キューで実行するようにディスパッチするのは非常に便利です。そのためにカスタムNSOperationまたはNSInvocationOperationを作成するには、さらに多くのサポートコードが必要です。私はあなたがNSBlockOperationを使うことができることを知っています、しかしあなたは同様にGCDに何かを派遣しているかもしれません。このコードをアプリケーション内の関連処理とインラインでブロック化すると、これらのタスクをカプセル化する個別のメソッドやカスタムNSOperationsを使用するよりもコード構成が改善されると私は思います。
NSOperationsとNSOperationQueuesにはまだ非常に優れた用途があります。 GCDには、NSOperationQueuesが非常に複雑な依存関係グラフを設定できる、依存関係の本当の概念はありません。いくつかのケースでは、これにNSOperationQueuesを使用します。
全体として、私は通常、タスクを達成するための最高レベルの抽象化を使用することを提唱していますが、これは私がGCDの低レベルAPIを主張する1つのケースです。私がこれについて話したiOSとMacの開発者の間で、彼らがそれをサポートしないでOSバージョンをターゲットにしていない限り、大多数はNSOperationsの上にGCDを使うことを選びます。
GCD
は、低レベルのCベースのAPIです。NSOperation
およびNSOperationQueue
はObjective-Cのクラスです。NSOperationQueue
は、GCD
に対するObjective Cのラッパーです。 NSOperationを使用している場合は、 Grand Central Dispatch.を暗黙的に使用しています。
NSOperationに対するGCDの優位性:
私。実装GCD
の実装は非常に軽量ですNSOperationQueue
は複雑で重いです
GCDよりもNSOperationの利点:
私。動作制御NSOperation
を一時停止、キャンセル、再開できます
ii。依存関係
2つのNSOperations
の間に依存関係を設定することができます
操作は、すべての依存関係が終了に対してtrueを返すまで開始されません。
iii。動作状態
は、操作または操作キューの状態をモニターできます。準備完了、実行中または終了
iv。最大操作数
同時に実行できるキュー操作の最大数を指定できます
GCD
またはNSOperation
に移動する場合_
(上記のすべての)キューをもっと制御したい場合はNSOperation
を使用し、オーバーヘッドを少なくしたい(バックグラウンドで作業を少しだけ行いたい場合)単純な場合はGCD
を使用します。
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.htmlhttp:/ /nshipster.com/nsoperation/
GCDよりもNSOperationを好むもう1つの理由は、NSOperationのキャンセルメカニズムです。たとえば、500pxのように何十枚もの写真を表示するApp、NSOperationを使用すると、テーブルビューまたはコレクションビューをスクロールしたときに表示されない画像セルの要求をキャンセルできます。 GCDはこれを簡単にはサポートできません。
NSOperationでもKVOは可能です。
ここで はEschatonの記事で、読む価値があります。
GCDは、実際にはNSOperationQueueよりも低レベルです。その主な利点は、その実装が非常に軽量で、ロックフリーのアルゴリズムとパフォーマンスに重点が置かれていることです。
NSOperationQueueはGCDで利用できない機能を提供しますが、それらは自明ではないコストで、NSOperationQueueの実装は複雑で重く、たくさんのロックを含み、GCDを内部的に使用するのはごくわずかです。
NSOperationQueueで提供されている機能が必ず必要な場合はそれを使用しますが、GCDで十分な場合は、パフォーマンスの向上、CPUと電力の大幅なコスト削減、および柔軟性の向上のために直接使用してください。
NSQueueOperationsとGCDはどちらも、UIアプリケーションのメイントレッドを解放することによって、バックグラウンドで別々のスレッドで大量の計算タスクを実行することを可能にします。
さて、前回の投稿に基づいて、NSOperationsにaddDependencyがあるので、順番に操作を順番にキューに入れることができます。
しかし、私はあなたがdispatch_queue_createを使用してキューであなたのオペレーションを実行するために作成できるGCDシリアルキューについても読んでいます。これにより、一連の操作を順次実行することができます。
GCDを超えるNSQueueOperationの利点:
依存関係を追加したり、依存関係を削除したりできるので、あるトランザクションでは依存関係を使用して順次実行でき、他のトランザクションでは同時に実行できますが、GCDではこの方法では実行できません。
操作がキュー内にある場合は、その操作を取り消すのは簡単です。実行中の場合は、操作を停止できます。
最大同時操作数を定義できます。
キューに入っている操作を中断できます
キューに保留中の操作がいくつあるかがわかります。
GCDは非常に使いやすいです - あなたがバックグラウンドで何かをしたいならば、あなたがする必要があるのはコードを書いてバックグラウンドキューにそれをディスパッチすることだけです。 NSOperationで同じことをすることは多くの追加作業です。
NSOperationの利点は、(a)メッセージを送信できる実際のオブジェクトがあること、および(b)NSOperationをキャンセルできることです。それは些細なことではありません。 NSOperationをサブクラス化する必要があります。キャンセルとタスクの正常終了の両方が正しく機能するように、コードを正しく記述する必要があります。単純なものにはGCDを使い、もっと複雑なものにはNSOperationのサブクラスを作ります。 (NSInvocationOperationとNSBlockOperationというサブクラスがありますが、それらが行うことはすべてGCDを使用する方が簡単なので、それらを使用する理由はありません)。
NSOperationsは、Grand Central Dispatchの上に構築された単なるAPIです。したがって、NSOperationsを使用しているときは、まだGrand Central Dispatchを使用しています。 NSOperationsがあなたが好むかもしれないいくつかの素晴らしい機能をあなたに与えるのはまさにその通りです。いくつかの操作を他の操作に依存させたり、アイテムを埋め込んだ後でキューを並べ替えることなどができます。実際、ImageGrabberはすでにNSOperationsと操作キューを使用しています。 ASIHTTPRequestは内部でそれらを使用します。また、必要に応じてさまざまな動作に使用するオペレーションキューを設定できます。それで、あなたはどちらを使うべきですか?あなたのアプリにはどちらでも構いません。このアプリの場合は非常に簡単なので、Grand Central Dispatchを直接使用しただけで、NSOperationの優れた機能は不要です。しかし、あなたがあなたのアプリのためにそれらを必要とするならば、それを使ってください。