Why should I choose GCD over NSOperation and blocks for high-level applications?

Lio picture Lio · Oct 4, 2011 · Viewed 17.4k times · Source

Apple's Grand Central Dispatch reference says:

"...if your application needs to operate at the Unix level of the system—for example, if it needs to manipulate file descriptors, Mach ports, signals, or timers. GCD is not restricted to system-level applications, but before you use it for higher-level applications, you should consider whether similar functionality provided in Cocoa (via NSOperation and block objects) would be easier to use or more appropriate for your needs.".

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

I can't actually think of situations, for high-level applications, in which the use of GCD is mandatory and NSOperation could/should not be used.

Any thoughts?

Answer

Brad Larson picture Brad Larson · Oct 4, 2011

The point being made here is the same one that Chris Hanson states in his article "When to use NSOperation vs. GCD":

The straightforward answer is a general guideline for all application development:

Always use the highest-level abstraction available to you, and drop down to lower-level abstractions when measurement shows that they are needed.

In this particular case, it means that when writing Cocoa applications, you should generally be using NSOperation rather than using GCD directly. Not because of a difference in efficiency, but because NSOperation provides a higher-level abstraction atop the mechanisms of GCD.

In general, I agree with this. NSOperation and NSOperationQueue provide support for dependencies and one or two other things that GCD blocks and queues don't have, and they abstract away the lower-level details of how the concurrent operations are implemented. If you need that functionality, NSOperation is a very good way to go.

However, after working with both, I've found myself replacing all of my NSOperation-based code with GCD blocks and queues. I've done this for two reasons: there is significant overhead when using NSOperation for frequent actions, and I believe my code is cleaner and more descriptive when using GCD blocks.

The first reason comes from profiling in my applications, where I found that the NSOperation object allocation and deallocation process took a significant amount of CPU resources when dealing with small and frequent actions, like rendering an OpenGL ES frame to the screen. GCD blocks completely eliminated that overhead, leading to significant performance improvements.

The second reason is more subjective, but I believe that my code is cleaner when using blocks than NSOperations. The quick capture of scope allowed by a block and the inline nature of them make for less code, because you don't need to create custom NSOperation subclasses or bundle up parameters to be passed into the operation, and more descriptive code in my opinion, because you can place the code to be run in a queue at the point where it is fired off.

Again, its a matter of preference, but I've found myself using GCD more, even in otherwise more abstracted Cocoa applications.