NSOperation vs Grand Central Dispatch

Estoy aprendiendo sobre la progtwigción concurrente para iOS. Hasta ahora he leído sobre NSOperation / NSOperationQueue y GCD . ¿Cuáles son las razones para usar NSOperationQueue sobre GCD y viceversa?

Parece que tanto GCD como NSOperationQueue resumen la creación explícita de NSThreads del usuario. Sin embargo, la relación entre los dos enfoques no es clara para mí, ¡así que cualquier comentario será apreciado!

GCD es una API de bajo nivel basada en C que permite un uso muy simple de un modelo de concurrencia basado en tareas. NSOperation y NSOperationQueue son clases Objective-C que hacen algo similar. NSOperation se introdujo primero, pero a partir de 10.6 e iOS 4, NSOperationQueue y sus amigos se implementan internamente utilizando GCD .

En general, debe usar el más alto nivel de abstracción que se adapte a sus necesidades. Esto significa que normalmente debe usar NSOperationQueue lugar de GCD , a menos que necesite hacer algo que NSOperationQueue no admita.

Tenga en cuenta que NSOperationQueue no es una versión ” NSOperationQueue ” de GCD; de hecho, hay muchas cosas que puede hacer de manera muy simple con NSOperationQueue que NSOperationQueue mucho trabajo con GCD puro. (Ejemplos: colas con ancho de banda restringido que solo ejecutan N operaciones a la vez; establecimiento de dependencias entre operaciones. Ambos son muy sencillos con NSOperation , muy difícil con GCD ). Apple ha hecho todo el trabajo de aprovechar GCD para crear una muy agradable API amigable para objetos con NSOperation . Aproveche su trabajo a menos que tenga una razón para no hacerlo.

Advertencia : por otro lado, si realmente necesita enviar un bloque y no necesita ninguna de las funciones adicionales que proporciona NSOperationQueue , no hay nada de malo en usar GCD. Solo asegúrese de que sea la herramienta correcta para el trabajo.

De acuerdo con mi respuesta a una pregunta relacionada , voy a estar en desacuerdo con BJ y sugiero que primero mire GCD por encima de NSOperation / NSOperationQueue, a menos que este último proporcione algo que necesita que GCD no lo haga.

Antes de GCD, utilicé una gran cantidad de NSOperations / NSOperationQueues dentro de mis aplicaciones para gestionar la concurrencia. Sin embargo, desde que comencé a usar GCD de forma regular, he reemplazado casi por completo NSOperations y NSOperationQueues con bloques y cola de despacho. Esto proviene de cómo utilicé ambas tecnologías en la práctica, y de los perfiles que he realizado en ellas.

Primero, hay una cantidad no trivial de sobrecarga al usar NSOperations y NSOperationQueues. Estos son objetos de cocoa, y deben ser asignados y desasignados. En una aplicación de iOS que escribí que representa una escena 3-D a 60 FPS, estaba usando NSOperations para encapsular cada fotogtwig procesado. Cuando hice un perfil de esto, la creación y el desassembly de estas NSOperations representaban una parte importante de los ciclos de la CPU en la aplicación en ejecución y disminuían la velocidad. Los reemplacé con bloques simples y una cola de serie de GCD, y esa sobrecarga desapareció, lo que mejoró notablemente el rendimiento de la representación. Este no fue el único lugar donde noté sobrecarga al usar NSOperations, y lo he visto tanto en Mac como en iOS.

En segundo lugar, hay un código de envío basado en la elegancia al locking que es difícil de igualar cuando se utilizan NSOperations. Es tan increíblemente conveniente envolver unas pocas líneas de código en un bloque y enviarlo para que se realice en una cola en serie o simultánea, donde la creación de una operación NSOperation o NSInvocationOperation personalizada para hacer esto requiere mucho más código de soporte. Sé que puedes usar NSBlockOperation, pero también podrías enviar algo a GCD. En mi opinión, envolver este código en bloques en línea con el procesamiento relacionado en su aplicación me lleva a una mejor organización del código que tener métodos separados o NSOperations personalizadas que encapsulan estas tareas.

NSOperations y NSOperationQueues aún tienen muy buenos usos. GCD no tiene un concepto real de dependencias, donde NSOperationQueues puede configurar gráficos de dependencia bastante complejos. Yo uso NSOperationQueues para esto en un puñado de casos.

En general, si bien generalmente defiendo el uso del más alto nivel de abstracción que lleva a cabo la tarea, este es un caso en el que defiendo la API de nivel inferior de GCD. Entre los desarrolladores de iOS y Mac con los que he hablado, la gran mayoría opta por usar GCD en NSOperations a menos que estén apuntando a versiones de sistema operativo sin soporte (las anteriores a iOS 4.0 y Snow Leopard).

GCD es una API basada en C de bajo nivel.
NSOperation y NSOperationQueue son clases Objective-C.
NSOperationQueue es un contenedor de NSOperationQueue C sobre GCD . Si está utilizando NSOperation, está implícitamente usando Grand Central Dispatch.

GCD ventaja sobre NSOperation:
yo. implementación
Para la implementación de GCD es muy ligero
NSOperationQueue es complejo y de gran peso

Ventajas de NSOperation sobre GCD:

yo. Control en funcionamiento
puede Pausar, Cancelar, Reanudar una NSOperation

ii. Dependencias
puede configurar una dependencia entre dos NSOperations
la operación no comenzará hasta que todas sus dependencias devuelvan verdadero para terminado.

iii. Estado de la operación
puede monitorear el estado de una operación o cola de operación. listo, ejecutando o terminado

iv. Número máximo de operaciones
puede especificar el número máximo de operaciones en cola que pueden ejecutarse simultáneamente

Cuándo ir para GCD o NSOperation
cuando desee más control sobre la cola (todo lo mencionado anteriormente) use NSOperation y para casos simples en los que desee menos sobrecarga (solo desea hacer algo de trabajo “en segundo plano” con muy poco trabajo adicional) use GCD

árbitro:
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 es de hecho de un nivel más bajo que NSOperationQueue, su principal ventaja es que su implementación es muy ligera y se centra en algoritmos y rendimiento sin locking.

NSOperationQueue proporciona instalaciones que no están disponibles en GCD, pero tienen un costo no trivial, la implementación de NSOperationQueue es compleja y pesada, implica un gran locking y utiliza GCD internamente solo de manera muy mínima.

Si necesita las instalaciones proporcionadas por NSOperationQueue, utilícela, pero si GCD es suficiente para sus necesidades, le recomendaría usarla directamente para un mejor rendimiento, un costo de CPU y energía significativamente más bajo y más flexibilidad.

Otra razón para preferir NSOperation sobre GCD es el mecanismo de cancelación de NSOperation. Por ejemplo, una aplicación como 500px que muestra docenas de fotos, use NSOperation, podemos cancelar solicitudes de celdas de imagen invisibles cuando desplazamos la vista de tabla o la vista de colección, esto puede mejorar enormemente el rendimiento de la aplicación y reducir la huella de memoria. GCD no puede soportar esto fácilmente.

También con NSOperation, KVO puede ser posible.

Aquí hay un artículo de Eschaton que vale la pena leer.

Tanto NSQueueOperations como GCD permiten ejecutar tareas de computación pesadas en segundo plano en hilos separados liberando la banda de rodadura principal de la aplicación de interfaz de usuario.

Bueno, en la publicación anterior basada vemos que NSOperations tiene addDependency para que pueda poner en cola su operación una detrás de otra secuencialmente.

Pero también leí sobre Colas de serie de GCD que puede crear para ejecutar sus operaciones en la cola usando dispatch_queue_create. Esto permitirá ejecutar un conjunto de operaciones una tras otra de forma secuencial.

Ventajas de NSQueueOperation sobre GCD:

  1. Permite agregar dependencia y le permite eliminar la dependencia, por lo que para una transacción puede ejecutarla secuencialmente usando la dependencia y para que otras transacciones se ejecuten simultáneamente, mientras que GCD no permite que se ejecute de esta manera.

  2. Es fácil cancelar una operación si está en la cola, puede detenerse si se está ejecutando.

  3. Puede definir el número máximo de operaciones simultáneas.

  4. Puede suspender la operación que están en cola

  5. Puede encontrar cuántas operaciones pendientes hay en cola.

GCD es muy fácil de usar: si desea hacer algo en segundo plano, todo lo que necesita hacer es escribir el código y enviarlo en una cola de fondo. Hacer lo mismo con NSOperation es mucho trabajo adicional.

La ventaja de NSOperation es que (a) tiene un objeto real al que puede enviar mensajes, y (b) puede cancelar una NSOperation. Eso no es trivial. Necesita subclasificar NSOperation, debe escribir su código correctamente para que la cancelación y el correcto acabado de una tarea funcionen correctamente. Entonces, para cosas simples usas GCD, y para cosas más complicadas creas una subclase de NSOperation. (Hay subclases NSInvocationOperation y NSBlockOperation, pero todo lo que hacen es más fácil de hacer con GCD, por lo que no hay una buena razón para usarlas).

Bueno, NSOperations es simplemente una API construida sobre Grand Central Dispatch. Entonces, cuando estás usando NSOperations, realmente sigues usando Grand Central Dispatch. Es solo que NSOperations te da algunas características de lujo que te pueden gustar. Puede hacer que algunas operaciones dependan de otras operaciones, reordenar colas después de sumbitar elementos, y otras cosas por el estilo. ¡De hecho, ImageGrabber ya está usando NSOperations y colas de operaciones! ASIHTTPRequest los usa bajo el capó, y puede configurar la cola de operación que utiliza para un comportamiento diferente si lo desea. Entonces, ¿cuál deberías usar? Cualquiera que tenga sentido para tu aplicación. Para esta aplicación es bastante simple, así que solo usamos Grand Central Dispatch directamente, sin necesidad de las elegantes funciones de NSOperation. Pero si los necesita para su aplicación, ¡siéntase libre de usarlo!