what is the difference between DISPATCH_QUEUE_CONCURRENT and Global Concurrent Dispatch Queues - ios

I read here in the apple documentation that for creating concurrent queues both DISPATCH_QUEUE_CONCURRENT and Global Concurrent Dispatch Queues can be used however I am uncertain as to what the difference between the two is.
E.x.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ });
and
dispatch_queue_t queue = dispatch_queue_create("custom",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ });
I read something on barriers but not sure how it comes into the picture in relationship with these two. Can anybody please explain the use cases for both of these ?

There are four global concurrent queues, one for each of four different priorities, that always exist and that are always there if you need them. So you don't have to create a concurrent queue to execute some block in the background. dispatch_get_global_queue () returns one of these four queues.
You can, if you want, create your own queues and delete them when you don't need them anymore.
What you are reading about barriers: The global queues are used by everyone. Using a barrier in a queue that is used by everyone is let's say highly impolite. That's why you shouldn't use barriers in global queues, only in queues that you created yourself.

In the first case, you are requesting one of the "global queues" which are provided for your application. "Anyone, anywhere, in your app" can get an easy reference to that queue just by asking dispatch_get_global_queue() for it. The queues are, in effect, singletons. And, nearly all of the time, that's all you need. The OS helpfully builds them for you and makes them really easy for everybody (in your app) to get to.
dispatch_queue_create() is used in those rare times when you actually need "another queue." It's bound to your application just like all the other queues are, but you manage it yourself. You have to provide some means for other parts of your app to get that queue-handle. You might do this if, say, in your design it's really necessary for different kinds of requests to be placed onto different queues.
And, as I said, most of the time, the global queues are all you really need. (The OS makes them "really handy," and that's why they're "really handy.") Typically, you "put lots of messages on just a few queues," with a one-to-many or many-to-many or many-to-one relationship between readers and writers.

Related

Threads and Queues in iOS - not NSThread

I'd like to get a conceptual understanding of serial/concurrent queues and threads in iOS. I have a solid grasp of the queue data structure and how it's used.
Are threads just, in an unofficial sense, an abstraction of a queue? Meaning they're implemented using queue data structures. Each queue is then an actual thread, but they act as queues in that processes are executed in a first in, first out fashion?
That would stand for serial queues, as those DO indeed follow FIFO, but then concurrent queues are a different ball game. You don't know what processes are executing when, and even though you have them on one queue, they are actually getting fired on different threads wherever there is availability? Meaning that queues can actually contain or refer to multiple threads?
Any help or pointers to resources (not including apple documentation, which I'm currently going through) would be greatly appreciated.
Queues are one of the methods to create threads in iOS.
A thread is the current execution of a code.
The main thread (Thread 0) is actually the single thread which runs always during the app lifetime. The others, if they are not attached to a NSRunLoop which have something like while(1) { code...}, then they'll finish immediately after the code is executed.
Wikipedia should be your friend: https://en.wikipedia.org/wiki/Thread_(computing)

With dispatch_async, use your own individual queues or your own global queue?

So when using dispatch_async ...
Say you're making a network connection for example...
dispatch_queue_t otherQ = dispatch_queue_create(NULL, 0);
__weak MyClass *myself = self;
dispatch_async(otherQ,
^{
myself.searchResultsRA = [myself dataFrom:happyUrl ifError:nil];
dispatch_async(dispatch_get_main_queue(), ^{ if (after) after(); });
});
dispatch_release(otherQ);
Notice I am creating a queue "right there" for that call.
So, every call like that in the app, simply creates its own queue "there and then" to use.
Alternately, you can just create one queue as a global for your app, and keep it around, and always use that one same queue. (I guess, you'd really "never release it" it would just persist for the life of the app.)
(Note - I am not talking about Apple's "global queue" ..dispatch_get_global_queue .. nothing to do with that .. I simply mean you can create your own one queue and always use that same queue.)
I've never really understood if one approach is preferred or if there are dangers associated with either, or any other issues.
In short, which approach to use?
These alternatives accomplish very different things. If you create a new queue each time, then all of them can run at once. If you always use the same (serial; doesn't apply to concurrent ones) queue, the blocks on it will run one at a time in order.
You would typically use the latter in either of two situations:
To protect something that's not threadsafe from being used from more than one thread at once (most common use of serial queues)
To intentionally reduce the amount of concurrency in your app to conserve resources (whether that be memory, or server connections, or what).
In addition to the answer from #Catfish_Man, consider that you currently have no control over how many downloads you're running concurrently and that you have no ability to cancel the downloads if the user changes their mind. Do you really want to make the user wait for one thing before requesting another, or risk flooding the network with requests and having them all fail?
In general, should you really be using GCD, or should you really opt for the higher level NSOperationQueue APIs.
Ising GCD directly, while it may offer the 'minimum code to write', does come with drawbacks/compromises and you should make yourself aware of them before using that approach.

GCD vs custom queue

I was wondering what is the difference in performance between these two.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// perform complex operation
// dispatch back to main thread to update UI
});
dispatch_async(_myCustomConcurrentQueue, ^{
// perform complex operation
// dispatch back to main thread to update UI
});
My assumption is the GCD is used across the os and other applications, and it will need to perform very quick background tasks, and be finished quick. And custom queues that are created are separate from GCD and they can run a different task, and will be added back to the pool once they are released. And so my assumption is that my customQueue performs better than GCD for a complex operation.
What are your thoughts? Which performs better? Are they the same?
While the high-priority global queue might theoretically be faster (since you don't have to create the queue, slightly different thread priority), the difference between that and your own custom concurrent queue is unlikely to be observable. There are two reasons, though, that you might want to use your own custom queues:
Certain features, notably dispatch barriers, are unavailable in global queues, so if you need those features, you'll want to use custom queue.
Debugging your app, it can also be useful to use your own queues with meaningful names, so that you can more easily identify the individual threads in the debugger.
But there are no material performance reasons to choose high priority global concurrent queue vs a custom concurrent queue.
Well, you don't say how _myCustomConcurrentQueue was created (it could be a serial queue or a concurrent queue), but assuming that it's a concurrent queue then it will have potentially a different priority than the global concurrent queues, both in terms of how GCD dispatches blocks or functions from its internal "queue of queues" blocklist and in the actual thread priority of the thread(s) created to do the work!
Please read the dispatch_queue_create(3) man page and pay specific attention to the "GLOBAL CONCURRENT QUEUES" section. It contains some very informative verbiage on this exact topic (too much to cut-and-paste here).
I'm pretty sure that if you create your own queue, it ultimately gets added to the GCD behind the scenes. I guess it's more of a preference thing.

Is there any reason to share a dispatch queue?

I'm working on some code that I can't contact the original developer.
He passes a class a reference to another class's serial dispatch queue and I'm not seeing any purpose to him not just creating another dispatch queue (each class is a singleton).
It's not creating issues but I'd like to understand it further, so any insight into the positive implications is appreciated, thank you.
Edit: I suggest reading all the answers here, they explain a lot.
It's actually not a good idea to share queues in this fashion (and no, not because they are expensive - they're not, quite the converse). The rationale is that it's not clear to anyone but a queue's creator just what the semantics of the queue are. Is it serial? Concurrent? High priority? Low priority? All are possible, and once you start passing internal queues around which were actually created for the benefit of a specific class, the external caller can schedule work on it which causes a mutual deadlock or otherwise behaves in an unexpected fashion with the other items on that queue because caller A knew to expect concurrent behavior and caller B was thinking it was a serial queue, without any of the "gotchas" that concurrent execution implies.
Queues should therefore, wherever possible, be hidden implementation details of a class. The class can export methods for scheduling work against its internal queue as necessary, but the methods should be the only accessors since they are the only ones who know for sure how to best access and schedule work on that specific type of queue!
If it's a serial queue, then they may be intending to serialize access to some resource shared between all objects that share it.
Dispatch queues are somewhat expensive to create, and tie up system resources. If you can share one, the system runs more efficiently. For that matter, if your app does work in the background, using a shared queue allows you to manage a single pool of tasks to be completed. So yes, there are good reasons for using a shared dispatch queue.

Using a single shared background thread for iOS data processing?

I have an app where I'm downloading a number of resources from the network, and doing some processing on each one. I don't want this work happening on the main thread, but it's pretty lightweight and low-priority, so all of it can really happen on the same shared work thread. That seems like it'd be a good thing to do, because of the work required to set up & tear down all of these work threads (none of which will live very long, etc.).
Surprisingly, though, there doesn't seem to be a simple way to get all of this work happening on a single, shared thread, rather than spawning a new thread for each task. This is complicated by the large number of paths to achieving concurrency that seem to have cropped up over the years. (Explicit NSThreads, NSOperationQueue, GCD, etc.)
Am I over-estimating the overhead involved in spawning all of these threads? Should I just not sweat it, and use the easier thread-per-task approaches? Use GCD, and assume that it's smarter than I about thread (re)use?
Use GCD — it's the current official recommendation and it's less effort than any of the other solutions. If you explicitly need the things you pass in to occur serially (ie, as if on a single thread) then you can achieve that but it's probably smarter just to change, e.g.
[self doCostlyTask];
To:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^()
{
[self doCostlyTask];
dispatch_async(dispatch_get_main_queue(), ^()
{
// most UIKit tasks are permissible only from the main queue or thread,
// so if you want to update an UI as a result of the completed action,
// this is a safe way to proceed
[self costlyTaskIsFinished];
});
});
That essentially tells the OS "do this code with low priority wherever it would be most efficient to do it". The various things you post to any of the global queues may or may not execute on the same thread as each other and as the thread that dispatched them and may or may not occur concurrently. The OS applies the rules it considers optimal.
Exposition:
GCD is Apple's implementation of thread pooling, and they introduced closures (as 'blocks') at the same time to make it usable. So the ^(C-style args){code} syntax is a block/closure. That is, it's code plus the state of any variables (subject to caveats) that the code references. You can store and call blocks yourself with no GCD knowledge or use.
dispatch_async is a GCD function issues a block to the nominated queue. It executes the block on some thread at some time, and applies unspecified internal rules to do so in an optimal fashion. It'll judge that based on factors such as how many cores you have, how busy each is, what it's currently thinking on power saving (which may depend on power source), how the power costs for that specific CPU work out, etc.
So as far as the programmer is developed, blocks make code into something you can pass around as an argument. GCD lets you request that blocks are executed according to the best scheduling the OS can manage. Blocks are very lightweight to create and copy — a lot more so than e.g. NSOperations.
GCD goes beyond the basic asynchronous dispatch in the above example (eg, you can do a parallel for loop and wait for it to finish in a single call) but unless you have specific needs it's probably not all that relevant.
Surprisingly, though, there doesn't seem to be a simple way to get all
of this work happening on a single, shared thread, rather than
spawning a new thread for each task.
This is exactly what GCD is for. GCD maintains a pool of threads that can be used for executing arbitrary blocks of code, and it takes care of managing that pool for best results on whatever hardware is at hand. This avoids the cost of constantly creating and destroying threads and also saves you from having to figure out how many processors are available, etc.
Tommy provides the right answer if you really care that only a single thread should be used, but it sounds like you're really just trying to avoid creating one thread per task.
This is complicated by the large number of paths to achieving
concurrency that seem to have cropped up over the years. (Explicit
NSThreads, NSOperationQueue, GCD, etc.)
NSOperationQueue uses GCD, so you can use that if it makes life easier than using GCD directly.
Use GCD, and assume that it's smarter than I about thread (re)use?
Exactly.
I would use NSOperationQueue or GCD and profile. Can't imagine thread overhead will beat out network delays.
NSOperationQueue would let you limit the number of simultaneous operations, if they end up getting too greedy. In fact, you can limit it to one if you need to.

Resources