objective-c ios concurrency objective-c-blocks grand-central-dispatch

objective c - ¿Por qué debería elegir GCD sobre NSOperation y bloques para aplicaciones de alto nivel?



objective-c ios (5)

La referencia de Grand Central Dispatch de Apple dice:

"... si su aplicación necesita operar en el nivel Unix del sistema, por ejemplo, si necesita manipular descriptores de archivos, puertos Mach, señales o temporizadores. GCD no está restringido a aplicaciones a nivel de sistema, sino antes utilícelo para aplicaciones de nivel superior, debe considerar si una funcionalidad similar provista en Cocoa (a través de NSOperation y bloquear objetos) sería más fácil de usar o más apropiada para sus necesidades ".

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

Realmente no puedo pensar en situaciones, para aplicaciones de alto nivel, en las que el uso de GCD es obligatorio y la NSOperation podría / no debería usarse.

¿Alguna idea?


Bueno, NSOperation no tiene equivalentes a dispatch_source_t, dispatch_io, dispatch_data_t, dispatch_semaphore_t, etc ... También es algo más elevado.

Por otro lado, libdispatch no tiene equivalentes a las dependencias de la operación, las prioridades de la operación (las prioridades de la cola son algo diferentes), o KVO en las operaciones.


De hecho, acabo de leer sobre esto y, estoy seguro de que vendrá como sorpresa, las opiniones difieren.

No puedo pensar en un caso en el que tengas que usar GCD sobre NSOperation, pero eso no significa que tal caso no exista. Sin embargo, estoy de acuerdo con un sentimiento general en términos de codificación de mejores prácticas:

Si tiene un par de herramientas que se adaptan al trabajo (y en este caso, tiene NSOperation vs un bloque GCD), use la clase con el nivel más alto de abstracción (es decir, la API de nivel más alto). Por lo general, no solo es más fácil de usar / menos código, sino que también se beneficiará de posibles mejoras futuras introducidas en las API de nivel superior.


El punto que se señala aquí es el mismo que Chris Hanson afirma en su artículo " Cuándo usar NSOperation vs. GCD ":

La respuesta directa es una guía general para todo el desarrollo de aplicaciones:

Siempre use la abstracción de más alto nivel disponible para usted, y desplácese hacia abajo hasta abstracciones de nivel inferior cuando la medición muestre que son necesarias.

En este caso particular, significa que al escribir aplicaciones Cocoa, generalmente debería utilizar NSOperation en lugar de usar GCD directamente. No debido a una diferencia en la eficiencia, sino porque la NSOperation proporciona una abstracción de nivel superior sobre los mecanismos de GCD.

En general, estoy de acuerdo con esto. NSOperation y NSOperationQueue brindan soporte para dependencias y una o dos cosas más que los bloques y colas GCD no tienen, y abstraen los detalles de nivel inferior de cómo se implementan las operaciones concurrentes. Si necesita esa funcionalidad, NSOperation es una muy buena manera de hacerlo.

Sin embargo, después de trabajar con ambos, me encontré reemplazando todo mi código basado en NSOperation con bloques y colas GCD. He hecho esto por dos razones: hay una sobrecarga significativa cuando se utiliza NSOperation para acciones frecuentes, y creo que mi código es más limpio y más descriptivo cuando se usan bloques GCD.

La primera razón se debe a la creación de perfiles en mis aplicaciones, donde descubrí que la asignación de objetos NSOperation y el proceso de desasignación requerían una gran cantidad de recursos de CPU cuando se trataba de acciones pequeñas y frecuentes, como la visualización de un marco OpenGL ES en la pantalla. Los bloques GCD eliminaron completamente esa sobrecarga, lo que llevó a mejoras significativas en el rendimiento.

La segunda razón es más subjetiva, pero creo que mi código es más limpio cuando se usan bloques que las operaciones NSO. La captura rápida del alcance permitido por un bloque y la naturaleza en línea de ellos hacen que haya menos código, ya que no es necesario crear subclases NSOperation personalizadas o agrupar los parámetros para pasarlos a la operación, y en mi opinión, un código más descriptivo. porque puede colocar el código para que se ejecute en una cola en el punto donde se dispara.

Nuevamente, es una cuestión de preferencia, pero me he encontrado usando más GCD, incluso en aplicaciones Cocoa más abstractas.


Hay dos cosas que NSOperationQueue puede hacer que GCD no hace: la menor es la dependencia (agregar una operación a una cola pero decirle que solo se ejecute cuando ciertas otras operaciones hayan finalizado), y la principal es que NSOperation le brinda un objeto que puede recibir mensajes mientras se ejecuta la tarea, a diferencia de GCD que tiene bloques que no pueden recibir mensajes, excepto de una manera muy limitada. O bien necesitas estas dos características, o no las necesitas. Si no lo haces, usar GCD es mucho más fácil de usar.

Es por eso que los ejemplos útiles de NSOperation son siempre bastante complejos. Si fueran fáciles, usarías GCD en su lugar. Por lo general, crea una subclase de NSOperation, que será una cantidad significativa de trabajo, o utilizará una que otra persona haya creado.


  • Prefiera GCD donde la tarea no es muy compleja y se requiere un rendimiento óptimo de la CPU .
  • Prefiera NSOperationQueue donde la tarea es compleja y requiere cancelar o suspender un bloqueo y la administración de dependencias .

GCD es una forma liviana de representar unidades de trabajo que se ejecutarán simultáneamente. Usted no programa estas unidades de trabajo; El sistema se encarga de la programación por usted. Agregar dependencia entre bloques puede ser un dolor de cabeza. ¡Cancelar o suspender un bloque crea un trabajo adicional para usted como desarrollador!

NSOperation y NSOperationQueue agregan una pequeña sobrecarga adicional en comparación con GCD, pero puede agregar dependencia entre varias operaciones. Puede reutilizar, cancelar o suspender operaciones. NSOperation es compatible con la observación de valor-clave (KVO); por ejemplo, puede hacer que una NSOperation comience a ejecutarse escuchando NSNotificationCenter.

Para una explicación detallada, consulte esta pregunta: NSOperation vs Grand Central Dispatch