Pourquoi devrais-je choisir GCD sur NSOperation et bloquer pour les applications de haut niveau?

La reference Grand Central Dispatch d'Apple dit:

"… si votre application doit fonctionner au niveau Unix du système, par exemple, si elle doit manipuler des descripteurs de files, des ports Mach, des signaux ou des temporisateurs, GCD ne se limite pas aux applications au niveau du système, mais avant utilisez-le pour des applications de niveau supérieur, vous devriez considérer si une fonctionnalité similaire fournie dans Cocoa (via NSOperation et les objects de bloc) serait plus facile à utiliser ou plus appropriée à vos besoins. ".

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

Je ne peux pas vraiment penser à des situations, pour des applications de haut niveau, dans lesquelles l'utilisation de GCD est obligatoire et NSOperation pourrait / ne devrait pas être utilisé.

Des pensées?

Le point soulevé ici est le même que Chris Hanson dans son article " Quand utiliser NSOperation vs GCD ":

La réponse directe est une ligne direcsortingce générale pour tout développement d'application:

Utilisez toujours l'abstraction de plus haut niveau qui vous est accessible et passez aux abstractions de niveau inférieur lorsque les mesures montrent qu'elles sont nécessaires.

Dans ce cas particulier, cela signifie que lorsque vous écrivez des applications Cocoa, vous devez généralement utiliser NSOperation plutôt que d'utiliser directement GCD. Pas à cause d'une différence d'efficacité, mais parce que NSOperation fournit une abstraction de plus haut niveau sur les mécanismes de GCD.

En général, je suis d'accord avec cela. NSOperation et NSOperationQueue fournissent un support pour les dependencies et une ou deux autres choses que les blocs et les files d'attente GCD n'ont pas, et ils éliminent les détails de niveau inférieur de la façon dont les opérations simultanées sont implémentées. Si vous avez besoin de cette fonctionnalité, NSOperation est une très bonne solution.

Cependant, après avoir travaillé avec les deux, je me suis retrouvé à replace tout mon code NSOperation par des blocs et des files d'attente GCD. Je l'ai fait pour deux raisons: il y a un surcoût significatif lorsque NSOperation est utilisé pour des actions fréquentes, et je crois que mon code est plus propre et plus descriptif lors de l'utilisation de blocs GCD.

La première raison vient du profilage dans mes applications, où j'ai trouvé que le process d'allocation et de désallocation d'objects NSOperation prenait une quantité importante de ressources CPU lors de petites actions fréquentes, comme le rendu d'une trame OpenGL ES à l'écran. Les blocs GCD ont complètement éliminé ces frais généraux, entraînant des améliorations significatives de performance.

La deuxième raison est plus subjective, mais je crois que mon code est plus propre lorsque j'utilise des blocs que NSOperations. La capture rapide de la scope autorisée par un bloc et la nature en ligne de ceux-ci font less de code, car vous n'avez pas besoin de créer des sous-classs NSOperation personnalisées ou de regrouper les parameters à passer dans l'opération, et plus de code descriptif car vous pouvez placer le code à exécuter dans une queue à l'endroit où il a été déclenché.

Encore une fois, c'est une question de preference, mais je me suis retrouvé à utiliser plus de GCD, même dans des applications Cocoa autrement abstraites.

  • Préférez GCD où la tâche n'est pas très complexe et une performance CPU optimale est requirejse.
  • Préférez NSOperationQueue où la tâche est complexe et nécessite l' annulation ou la suspension d'une gestion de bloc et de dependencies .

GCD est un moyen léger de représenter des unités de travail qui vont être exécutées simultanément. Vous ne planifiez pas ces unités de travail; le système prend soin de la planification pour vous. L'ajout de dependencies entre les blocs peut être un casse-tête. L'annulation ou la suspension d'un bloc crée un travail supplémentaire pour vous en tant que développeur!

NSOperation et NSOperationQueue ajoutent un léger surcoût par rapport à GCD, mais vous pouvez append une dépendance entre différentes opérations. Vous pouvez réutiliser, annuler ou suspendre les opérations. NSOperation est compatible avec Key-Value Observation (KVO); Par exemple, vous pouvez démarrer NSOperation en écoutant NSNotificationCenter.

Pour une explication détaillée, référez-vous à cette question: NSOperation vs Grand Central Dispatch

Eh bien, NSOperation n'a aucun équivalent à dispatch_source_t, dispatch_io, dispatch_data_t, dispatch_semaphore_t, etc … C'est aussi un peu plus lourd.

D'un autre côté, libdispatch n'a pas d'équivalents aux dependencies d'opération, aux priorités d'opération (les priorités des files d'attente sont quelque peu différentes), ou aux opérations sur le KVO.

NSOperationQueue peut faire deux choses que GCD ne fait pas: La mineure est dependencies (append une opération à une queue mais lui dire de ne s'exécuter que lorsque certaines autres opérations sont terminées), et la plus importante est que NSOperation vous donne un object qui peut recevoir des messages pendant l'exécution de la tâche, contrairement à GCD qui a des blocs qui ne peuvent recevoir de messages que de façon très limitée. Vous avez besoin de ces deux fonctionnalités, ou vous ne le faites pas. Si vous ne le faites pas, utiliser GCD est beaucoup plus facile à utiliser.

C'est pourquoi des exemples utiles de NSOperation sont toujours assez complexes. Si elles étaient faciles, vous utiliseriez GCD à la place. Vous créez généralement une sous-class de NSOperation, ce qui représente une quantité importante de travail, ou en utilisez une que quelqu'un d'autre a créée.

En fait, je viens juste de lire à ce sujet, et je suis sûr que cela va venir comme surprise, les opinions diffèrent.

Je ne peux pas penser à un cas où vous auriez à utiliser GCD sur NSOperation, mais cela ne signifie pas qu'un tel cas n'existe pas. Je suis toutefois d'accord avec un sentiment général en termes de encoding des meilleures pratiques:

Si vous avez quelques outils qui conviennent au travail (et dans ce cas, vous avez NSOperation vs un bloc GCD), utilisez la class avec le plus haut niveau d'abstraction (c'est-à-dire l'API de plus haut niveau). Non seulement il est généralement plus facile d'utiliser / less de code, mais vous bénéficierez également des futures améliorations potentielles apscopes aux API de plus haut niveau.