iOSの並行プログラミングについて学んでいます。NSOperation
これまで/NSOperationQueue
とについて読んできましたGCD
。overを使用する理由とその逆を使用する理由は何ですか?NSOperationQueue
GCD
の両方のように聞こえ、ユーザーからの明示的な作成GCD
をNSOperationQueue
抽象化NSThreads
します。ただし、2 つのアプローチの関係は明確ではないので、フィードバックをいただければ幸いです。
iOSの並行プログラミングについて学んでいます。NSOperation
これまで/NSOperationQueue
とについて読んできましたGCD
。overを使用する理由とその逆を使用する理由は何ですか?NSOperationQueue
GCD
の両方のように聞こえ、ユーザーからの明示的な作成GCD
をNSOperationQueue
抽象化NSThreads
します。ただし、2 つのアプローチの関係は明確ではないので、フィードバックをいただければ幸いです。
GCD
は、タスクベースの同時実行モデルの非常に簡単な使用を可能にする低レベルのCベースのAPIです。NSOperation
とNSOperationQueue
は、同様のことを行うObjective-Cクラスです。NSOperation
が最初に導入されましたが、10.5およびiOS 2以降、NSOperationQueue
およびフレンドはを使用して内部的に実装されてGCD
います。
一般に、ニーズに合った最高レベルの抽象化を使用する必要があります。これは、サポートされていないことを行う必要がない限り、通常はNSOperationQueue
の代わりに使用する必要があることを意味します。GCD
NSOperationQueue
NSOperationQueue
これはGCDの「ダムダウン」バージョンではないことに注意してください。NSOperationQueue
実際、純粋で多くの作業を必要とする、非常に簡単に実行できることがたくさんありGCD
ます。(例:一度にN個の操作のみを実行する帯域幅に制約のあるキュー。操作間の依存関係を確立します。どちらも非常に単純でNSOperation
、非常に困難GCD
です。)Appleは、GCDを活用して非常に優れたオブジェクトフレンドリーなAPIを作成するという大変な作業を行いましNSOperation
た。あなたがそうしない理由がない限り、彼らの仕事を利用してください。
警告:一方、本当にブロックを送信する必要があり、NSOperationQueue
提供する追加機能が必要ない場合は、GCDを使用しても問題はありません。それが仕事に適したツールであることを確認してください。
関連する質問に対する私の回答に沿って、私は BJ に同意せず、まず NSOperation / NSOperationQueue よりも GCD を検討することをお勧めします。
GCD を導入する前は、並行性を管理するためにアプリケーション内で多くの NSOperations / NSOperationQueues を使用していました。しかし、定期的に GCD を使い始めてから、NSOperations と NSOperationQueues をほぼ完全にブロックとディスパッチ キューに置き換えました。これは、私が実際に両方のテクノロジーをどのように使用したか、およびそれらに対して実行したプロファイリングから得られたものです。
まず、NSOperations と NSOperationQueues を使用すると、かなりの量のオーバーヘッドが発生します。これらは Cocoa オブジェクトであり、割り当てと割り当て解除が必要です。3D シーンを 60 FPS でレンダリングする私が作成した iOS アプリケーションでは、レンダリングされた各フレームをカプセル化するために NSOperations を使用していました。これをプロファイリングしたところ、これらの NSOperations の作成と破棄は、実行中のアプリケーションの CPU サイクルのかなりの部分を占めており、速度が低下していました。これらを単純なブロックと GCD シリアル キューに置き換えたところ、そのオーバーヘッドがなくなり、レンダリング パフォーマンスが著しく向上しました。NSOperations の使用によるオーバーヘッドに気付いたのはこれだけではなく、Mac と iOS の両方でこれを確認しました。
2 つ目は、ブロックベースのディスパッチ コードには、NSOperations を使用するときに一致させるのが困難な優雅さがあります。数行のコードをブロックにラップし、シリアル キューまたはコンカレント キューで実行されるようにディスパッチするのは非常に便利です。これを行うには、さらに多くのサポート コードが必要になります。NSBlockOperation を使用できることはわかっていますが、その場合は何かを GCD にディスパッチすることもできます。私の意見では、このコードをアプリケーション内の関連する処理とインラインでブロックにラップすると、これらのタスクをカプセル化する個別のメソッドまたはカスタム NSOperations を使用するよりもコード構成が改善されます。
NSOperations と NSOperationQueues には、依然として非常に有効な用途があります。GCD には依存関係の実際の概念がなく、NSOperationQueues はかなり複雑な依存関係グラフを設定できます。少数のケースで、これに NSOperationQueues を使用します。
全体として、私は通常、タスクを達成する最高レベルの抽象化を使用することを主張していますが、これは GCD の低レベル API を主張する 1 つのケースです。これについて私が話した iOS および Mac 開発者の中で、サポートされていない OS バージョン (iOS 4.0 および Snow Leopard より前のバージョン) を対象としていない限り、圧倒的多数が NSOperations よりも GCD を使用することを選択しています。
GCD
低レベルの C ベースの API です。
NSOperation
およびNSOperationQueue
Objective-C クラスです。
NSOperationQueue
目的の C ラッパー オーバーGCD
です。NSOperation を使用している場合は、暗黙的にGrand Central Dispatch を使用しています。
NSOperation に対する GCD の利点:
i. 実装
実装
はGCD
非常に軽量
NSOperationQueue
で複雑で重い
GCD に対する NSOperation の利点:
私。操作
を制御すると、一時停止、キャンセル、再開できます。NSOperation
ii. 2 つの操作間の依存関係
を設定できる依存関係NSOperations
は、そのすべての依存関係が終了を表す true を返すまで開始されません。
iii. State of Operation
は、操作または操作キューの状態を監視できます。準備完了、実行中、または終了
iv。操作
の最大数 同時に実行できるキューに入れられた操作の最大数を指定できます
いつ行くGCD
かNSOperation
、または
キューをより細かく制御したい場合 (上記のすべて) を使用NSOperation
し、オーバーヘッドを減らしたい単純なケース (追加の作業をほとんど行わずに「バックグラウンドで」作業を行いたい場合) を使用します。GCD
参照:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/
http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html
http ://nshipster.com/nsoperation/
GCD よりも NSOperation を優先するもう 1 つの理由は、NSOperation のキャンセル メカニズムです。たとえば、数十枚の写真を表示する 500px のようなアプリでは、NSOperation を使用して、テーブル ビューまたはコレクション ビューをスクロールするときに非表示の画像セルの要求をキャンセルできます。これにより、アプリのパフォーマンスが大幅に向上し、メモリ フットプリントが削減されます。GCD はこれを簡単にサポートできません。
また、NSOperation を使用すると、KVO が可能になります。
これは、読む価値のあるEschatonの記事です。
GCD は確かに NSOperationQueue よりも低レベルです。その主な利点は、その実装が非常に軽量であり、ロックフリーのアルゴリズムとパフォーマンスに重点を置いていることです。
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 で行う方が簡単なので、それらを使用する正当な理由はありません)。