Вопрос по ios, concurrency – NSOperation vs Grand Central Dispatch

443

Я изучаю параллельное программирование для iOS. До сих пор я читал оNSOperation/NSOperationQueue а такжеGCD. What are the reasons for using NSOperationQueue over GCD and vice versa?

Звучит как обаGCD а такжеNSOperationQueue абстрагироваться от явного созданияNSThreads от пользователя. Однако связь между этими двумя подходами мне не ясна, поэтому любая обратная связь приветствуется!

+1 за хороший вопрос - любопытно по результатам. До сих пор я только что прочитал, что GCD может быть легко распределен между ядрами процессора, что делает его «новым горячим дерьмом». Till
cocoacasts.com/… Masih
Некоторое связанное обсуждение может быть найдено в этом вопросе:Why should I choose GCD over NSOperation and blocks for high-level applications? Brad Larson♦

Ваш Ответ

8   ответов
33

чем NSOperationQueue, его главное преимущество заключается в том, что его реализация очень легкая и ориентирована на алгоритмы и производительность без блокировок.

NSOperationQueue предоставляет средства, которые недоступны в GCD, но они имеют нетривиальную стоимость, реализация NSOperationQueue сложна и тяжела, включает в себя много блокировок и использует GCD изнутри только минимальным образом.

Если вам нужны средства, предоставляемые NSOperationQueue, во что бы то ни стало, используйте его, но если GCD достаточен для ваших нужд, я бы порекомендовал использовать его напрямую для повышения производительности, значительного снижения стоимости процессора и питания и большей гибкости.

81

GCD является низкоуровневым C-API.
NSOperation а такжеNSOperationQueue являются классами Objective-C.
NSOperationQueue является объективной оберткой CGCD. Grand Central Dispatch.

GCD advantage over NSOperation:
i. implementation
ЗаGCD реализация очень легкая
NSOperationQueue сложный и тяжелый

NSOperation advantages over GCD:

i. Control On Operation
Вы можете приостановить, отменить, возобновитьNSOperation

ii. Dependencies
Вы можете установить зависимость между двумяNSOperations
операция не начнется, пока все ее зависимости не вернут true для завершения.

iii. State of Operation
может отслеживать состояние операции или очереди операций. готов, выполняется или закончен

iv. Max Number of Operation
Вы можете указать максимальное количество операций в очереди, которые могут выполняться одновременно

When to Go for GCD or NSOperation
когда вы хотите больше контроля над очередью (все вышеупомянутое) используйтеNSOperation and for simple cases where you want less overhead (you just want to do some work "into the background" with very little additional work) use GCD

ref:
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/

Вей хорошо объяснил !! Спасибо !!
Это зависит от условий системы здесь подробная информация:stackoverflow.com/questions/14995801/…
Мы также можем отменить задачу в GCD с помощью DispatchWorkItem, а также можем приостановить и возобновить
Thakns @Sangram для подробной информации.
Как уже было сказано, максимальное число операций может быть указано в NSOperationQueue. Тогда каково может быть максимальное количество операций (очередей отправки) в GCD? Предположим, у меня есть проект. Тогда сколько операций (очередей отправки) я могу сделать. или их максимальные пределы, которые мы можем сделать.
23

и GCD позволяют выполнять сложные вычислительные задачи в фоновом режиме в отдельных потоках, освобождая основную программу приложения UI.

Итак, основываясь на предыдущем посте, мы видим, что NSOperations имеет addDependency, чтобы вы могли последовательно ставить свои операции в очередь.

Но я также читал о последовательных очередях GCD, которые вы можете создать для запуска своих операций в очереди с помощью dispatch_queue_create. Это позволит последовательно выполнять набор операций один за другим.

NSQueueOperation Преимущества перед GCD:

It allows to add dependency and allows you to remove dependency so for one transaction you can run sequential using dependency and for other transaction run concurrently while GCD doesn't allow to run this way.

It is easy to cancel an operation if it is in the queue it can be stopped if it is running.

You can define the maximum number of concurrent operations.

You can suspend operation which they are in Queue

You can find how many pending operations are there in queue.

Добро пожаловать :)
Спасибо, очень хорошее объяснение
33

по которой NSOperation предпочтительнее GCD, является механизм отмены NSOperation. Например, приложение, такое как 500px, которое показывает десятки фотографий, использует NSOperation, мы можем отменить запросы невидимых ячеек изображения, когда мы прокручиваем представление таблицы или представление коллекции, это может значительно улучшить производительность приложения и уменьшить объем памяти. GCD не может легко это поддержать.

Также с NSOperation KVO может быть возможным.

Вот это статья из Eschaton, которую стоит прочитать.

@algal как объяснил здесь (stackoverflow.com/questions/21918722/…), похоже, что NSURLSession использует NSOperationQueue в качестве строительного блока.
Стоит отметить, что если то, что вы отменяете, это сетевая операция загрузки образа, то вам не нужноNSOperation для этого, какNSURLSessionTask.cancel а такжеNSURLSession.invalidateAndCancel предоставить эту функциональность. В общем,NSURLSession обеспечивает некоторые функциональные возможностиNSOperationQueue, какNSURLSessionTask обеспечивает некоторые функциональные возможностиNSOperation
3

NSOperations - это просто API, созданный поверх Grand Central Dispatch. Поэтому, когда вы используете NSOperations, вы действительно все еще используете Grand Central Dispatch. Просто NSOperations дает вам некоторые интересные функции, которые вам могут понравиться. Вы можете сделать некоторые операции зависимыми от других операций, изменить порядок очередей после добавления элементов и тому подобное. Фактически, ImageGrabber уже использует NSOperations и очереди операций! ASIHTTPRequest использует их под капотом, и вы можете настроить очередь операций, которую он использует, для различного поведения, если вам это нравится. Так что вы должны использовать? Все, что имеет смысл для вашего приложения. Для этого приложения это довольно просто, поэтому мы просто использовали Grand Central Dispatch напрямую, без необходимости в причудливых функциях NSOperation. Но если они нужны для вашего приложения, не стесняйтесь использовать его!

357

мой ответ на связанный вопросЯ собираюсь не согласиться с BJ и предложить вам сначала взглянуть на GCD через NSOperation / NSOperationQueue, если только последний не предоставляет что-то, что вам нужно, что GCD не делает.

До GCD я использовал много NSOperations / NSOperationQueues в своих приложениях для управления параллелизмом. Однако, поскольку я начал использовать GCD на регулярной основе, я почти полностью заменил NSOperations и NSOperationQueues на блоки и очереди отправки. Это произошло из-за того, что я использовал обе технологии на практике, и из того, как я их профилировал.

Во-первых, при использовании NSOperations и NSOperationQueues нетривиальные издержки. Это объекты Какао, и они должны быть выделены и освобождены. В написанном мною приложении iOS, которое визуализирует трехмерную сцену со скоростью 60 кадров в секунду, я использовал NSOperations для инкапсуляции каждого визуализированного кадра. Когда я рассказал об этом, создание и разборка этих NSOperations составляли значительную часть циклов ЦП в работающем приложении и замедляли работу. Я заменил их простыми блоками и последовательной очередью GCD, и эти издержки исчезли, что привело к заметно лучшей производительности рендеринга. Это было не единственное место, где я заметил накладные расходы от использования NSOperations, и я видел это как на Mac, так и на iOS.

Во-вторых, существует элегантность блочного кода диспетчеризации, который трудно сопоставить при использовании NSOperations. Это невероятно удобно заключать в строку несколько строк кода и отправлять их для выполнения в последовательную или параллельную очередь, где для создания пользовательской NSOperation или NSInvocationOperation для этого требуется гораздо больше вспомогательного кода. Я знаю, что вы можете использовать NSBlockOperation, но вы можете отправлять что-то в GCD. Заключение этого кода в блоки в соответствии с соответствующей обработкой в вашем приложении, на мой взгляд, приводит к лучшей организации кода, чем использование отдельных методов или пользовательских операций NSO, которые инкапсулируют эти задачи.

NSOperations и NSOperationQueues по-прежнему имеют очень хорошее применение. GCD не имеет реальной концепции зависимостей, где NSOperationQueues может создавать довольно сложные графы зависимостей. Я использую NSOperationQueues для этого в нескольких случаях.

В целом, хотя я обычно выступаю за использование самого высокого уровня абстракции, который выполняет задачу, это один из случаев, когда я спорю о низкоуровневом API GCD. Среди разработчиков iOS и Mac, с которыми я говорил об этом, подавляющее большинство предпочитают использовать GCD поверх NSOperations, если они не нацелены на версии ОС без поддержки этого (те, что до iOS 4.0 и Snow Leopard).

Я только слегка не согласен; Я использую обычный GCD совсем немного. Но я думаю, что в этом ответе вы слишком сильно игнорируете NSBlockOperation. Все преимущества NSOperationQueue (зависимости, отладка и т. Д.) Применимы и к блочным операциям.
@BJHomer - Я думаю, что избегание NSBlockOperation - это скорее вопрос личных предпочтений в моем случае, хотя я вообще уклонился от операций NSOperation. Если я собираюсь использовать блоки, я склонен идти ва-банк в GCD, за редким исключением, когда мне нужна поддержка зависимостей.
@VolureDarkAngel - GCD очень быстро обрабатывает такие отправки. Это не должно быть вашим узким местом в ситуации, как вы описываете, если только вы не скопируете кучу обновлений в очередь из-за медленного доступа к вводу / выводу или чего-то в этом роде. Это, вероятно, здесь не тот случай.
+1, спасибо за этот анализ. Apple, похоже, поддерживает оба (например, сеанс WWDC 2012 по параллельному интерфейсу), так что это очень ценится.
@ asma22 - Распространены расчеты, которые можно выполнять по частям, но для окончательного расчета одного этапа могут потребоваться результаты нескольких предыдущих этапов. В этом случае вы можете сделать эту более позднюю операцию зависимой от более ранних операций, и планирование будет управляться таким образом, чтобы все они выполнялись до выполнения последней.
495

GCD является низкоуровневым API на основе C, который позволяет очень просто использовать модель параллелизма на основе задач.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, Воспользуйтесь их работой, если у вас нет причин не делать этого.

Caveat: On the other hand, if you really just need to send off a block, and don't need any of the additional functionality that NSOperationQueue обеспечивает, нет ничего плохого в использовании GCD. Просто убедитесь, что это правильный инструмент для работы.

NSOperation, чтобы быть конкретным абстрактным классом.
значит GCD это обертка в очереди NSoperation и Nsoperation ???
@ Sandy На самом деле все наоборот, GCD используется NSOperation (по крайней мере, в более поздних версиях iOS и OS X).
@BJ Homer Мы можем добавить задачу в очередь последовательной отправки, чтобы получить зависимость. так просто, как очередь работы имеют преимущество перед этим
@RajAggrawal Да, это работает & # x2026; но тогда вы застряли в последовательной очереди. NSOperation может выполнить «эту операцию после того, как будут выполнены остальные три, но одновременно со всеми другими происходящими вещами». Операционные зависимости могут даже существовать между операциями в разных очередях. Большинству людей это не нужно, но если вы это сделаете, NSOperation будет лучшим выбором.
5

вом режиме, все, что вам нужно сделать, это написать код и отправить его в фоновую очередь. Делать то же самое с NSOperation - это много дополнительной работы.

Преимущество NSOperation заключается в том, что (а) у вас есть реальный объект, на который вы можете отправлять сообщения, и (б) вы можете отменить NSOperation. Это не тривиально. Вам необходимо создать подкласс NSOperation, вы должны правильно написать свой код, чтобы отмена и правильное завершение задачи работали правильно. Так что для простых вещей вы используете GCD, а для более сложных вещей вы создаете подкласс NSOperation. (Существуют подклассы NSInvocationOperation и NSBlockOperation, но все, что они делают, легче сделать с помощью GCD, поэтому нет веских оснований для их использования).

Похожие вопросы