dispatch_async and [NSURLConnection sendSynchronousRequest] - ios

There are various questions around this topic, and lots of advice saying NOT to use sendSynchronousRequest within dispatch_async, because it blocks the thread, and GCD will spawn lots of new worker threads to service all the synchronous URL requests.
Nobody seems to have a definitive answer as to what iOS 5, [NSURLConnection sendAsynchronousRequest:queue:completionHandler:] does behind the scenes.
One post I read states that it 'might' optimise, and it 'might' use the run loop - but certainly won't create a new thread for each request.
When I pause my debugger when using sendAsynchronousRequest:queue:completionHandler, the stack trace looks like this:
..now it appears that sendAsynchronousRequest:queue:completionHandler, is actually calling sendSynchronousRequest, and I still have tons of threads created when I use the async method instead of the sync method.
Yes, there are other benefits to using the async call, which I don't want to discuss in this post.
All I'm interested in is performance / thread / system usage, and if i'm worse off using the sync call inside dispatch_async instead of using the async call.
I don't need advice on using ios4 async calls either, this is purely for educational purposes.
Does anyone have any insightful answers to this?
Thanks

This is actually open source. http://libdispatch.macosforge.org/
It is very unlikely that you will be able to manage the worker threads more efficiently than Apple's implementation. In this context "asynchronous" doesn't mean select/poll, it just means that the call will return immediately. So it is not surprising that the implementation is spawning threads.

As the previous answer stated, both GCD (libdispatch) and the libblocksruntime are open source. Internally, iOS/OS X manage a global pool of pthreads, plus any app-specific pools you create in your user code. Since there's a 1:N mapping between OS threads and dispatch tasks, you don't have to (and shouldn't) worry about thread creation and disposal under the hood. To that end, a GCD task doesn't use any time in an app's run loop after invocation as it's punted to a background thread.
Most kinds of NSURL operations are I/O-bound; there's no amount of concurrency voodo that can disguise this, but if Apple's own async implementation uses its synchronous counterpart in the background, it probably suggests it's quite highly optimized already. Contrary to what the previous answer said, libdispatch does use scalable I/O internally (kqueue on OS X/iOS/BSD), and if you hand-rolled something yourself you'd have to deal with file-descriptor readiness yourself to yield similar performance.
While possible, the return on time invested is probably marginal. Stick with Apple's implementation and stop worrying about threads!

Related

Why use GCD and blocks for HTTP downloads?

In a job interview, I was asked why I should use blocks and GCD instead of NSURLConnection in order to download files asyncronously. After some research I haven't found a good reason to do that. I have multiple apps where I use just NSURLConnection just fine for multiple simultaneous downloads. Is their question attempting to ascertain whether I'm conforming to whatever is trendy (GCD, blocks) or is there any actual, substantial advantage to doing async fetches in this way?
Thanks.
In iOS 7, you generally should not use block-based methods to download files asynchronously. In order to support background transfers, you must use NSURLSession with delegate methods, and cannot use the block-based methods. Beyond that, I'm not sure what is meant here by "instead of NSURLConnection" in any case.
If they meant sendAsynchronousRequest:queue:completionHandler: (which is NSURLConnection), it's convenient, but much less flexible and powerful than the delegate-based NSURLConnection, so the only answer I would have is "because sometimes it's more convenient, and keeps the code closer together, when you don't need much flexibility."
Unless what they actually mean is the part of GCD that really does this: Dispatch I/O. There are reasons to use that directly (particularly if you're using non-HTTP protocols, or if you're managing an HTTP server rather than a client), but they're rare, and not usually for "downloading files asynchronously." The higher level APIs are preferred in most cases.
If you were doing many, many connections, transferring a ton of data over a very fast network connection, I can perhaps see how NSURLConnection's use the runloop for I/O handling and callbacks might become problematic, if you're scheduling these NSURLConnections on the main runloop. That said, you could just as easily spool up a lower priority background thread with its own runloop to keep those operations off the main thread.
If you didn't need all the extra machinery of NSURLConnection (caching, authentication, etc), dispatch_io* is almost certainly a lower overhead mechanism for handling raw network I/O, but you would really be giving up quite a bit of functionality for what I expect, practically speaking, to be a very marginal performance improvement.
I'm not sure. Mainly because NSURLConnection's sendAsynchronousRequest method has a completion handler built into it which uses a block.
Maybe a trick question? To me, it seems like the interviewer just wanted to see if you could conclude that they both can serve the same function.
Blocks and GCD aren't specifically for downloads, but they can make downloading easier. You would have to use them in conjunction with something that did the downloading (like NSURLConnection).
The advantage of using GCD with an NSURLConnection is that you can package it together nicely and don't have to rely on spread-out delegate methods. You can limit the number of connections easily too as well as pausing and stopping connections.
My "go to" set up for complex networking is to use an NSOperationQueue and NSOperation subclasses to do the work.
Each operation then uses a NSURLConnection and its delegate methods to download the data and then process it.
In a way this is already using GCD through the NSOperationQueue but I can't see a reason to use any other method combining blocks and GCD etc...
Did they give you a "correct" answer?

What is the best networking solution for a complex multithreaded app?

I have a streaming iOS app that captures video to Wowza servers.
It's a beast, and it's really finicky.
I'm grabbing configuration settings from a php script that shoots out JSON.
Now that I've implemented that, I've run into some strange threading issues. My app connects to the host, says its streaming, but never actually sends packets.
Getting rid of the remote configuration NSURLConnection (which I've made sure is properly formatted) delegate fixes the problem. So I'm thinking either some data is getting misconstrued across threads or something like that.
What will help me is knowing:
Are NSURLConnection delegate methods called on the main thread?
Will nonatomic data be vulnerable in a delegate method?
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Have you looked at AFNetworking?
http://www.raywenderlich.com/30445/afnetworking-crash-course
https://github.com/AFNetworking/AFNetworking
It's quite robust and helps immensely with the threading, and there are several good tutorials.
Are NSURLConnection delegate methods called on the main thread?
Yes, on request completion it gives a call back on the main thread if you started it on the main thread.
Will nonatomic data be vulnerable in a delegate method?
Generally collection values (like array) are vulnerable with multiple threads; the rest shouldn't create anything other than a race problem.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
I feel it's better to use GCD for handling your threads, and asynchronous retrieval using NSURLConnection should be helpful. There are few network libraries available to do the boilerplate code for you, such as AFNetworking, and ASIHTTPRequest (although that is a bit old).
Are NSURLConnection delegate methods called on the main thread?
Delegate methods can be executed on a NSOperationQueue or a thread. If you not explicitly schedule the connection, it will use the thread where it receives the start message. This can be the main thread, but it can also any other secondary thread which shall also have a run loop.
You can set the thread (indirectly) with method
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode
which sets the run loop which you retrieved from the current thread. A run loop is associated to a thread in a 1:1 relation. That is, in order to set a certain thread where the delegate methods shall be executed, you need to execute on this thread, retrieve the Run Loop from the current thread and send scheduleInRunLoop:forMode: to the connection.
Setting up a dedicated secondary thread requires, that this thread will have a Run Loop. Ensuring this is not always straight forward and requires a "hack".
Alternatively, you can use method
- (void)setDelegateQueue:(NSOperationQueue *)queue
in order to set the queue where the delegate methods will be executed. Which thread will be actually used for executing the delegates is then undetermined.
You must not use both methods - so schedule on a thread OR a queue. Please consult the documentation for more information.
Will nonatomic data be vulnerable in a delegate method?
You should always synchronize access to shared resources - even for integers. On certain multiprocessor systems it is not even guaranteed that accesses to a shared integer is safe. You will have to use memory barriers on both threads in order to guarantee that.
You might utilize serial queues (either NSOperationQueue or dispatch queue) to guarantee safe access to shared resources.
When dealing with a complex threaded app, what are the best practices for grabbing data from the web?
Utilize queues, as mentioned, then you don't have to deal with threads. "Grabbing data" is not only a threading problem ;)
If you prefer a more specific answer you would need to describe your problem in more detail.
To answer your first question: The delegate methods are called on the thread that started the asynchronous load operation for the associated NSURLConnection object.

What I should use for parallelisation of frequent HTTP requests to the REST server in iOS application: GCD or NSThread?

I'm developing an application which must extract new messages for user from the server. I have implemented this as a timer which fires every 2 seconds and call a selector which is a method that implement HTTP request and server respond processing. So I think it is quite a bad idea to do this in a main thread.I have no experience with multithreading in iOS. So I want to know what fits well for parallelizing of this task: GCD or NSThread?
You should work as far up the API stack as possible. That way you can concentrate on programming functionality and not managing threads. GCD uses threads that the system has gotten going anyway and its much more efficient than managing your own code. Its even better to aim to encapsulate your networking into NSOperations that can then be put on an NSOperationQueue and these will be executed on one or more background threads, whatever the system deems is a good number for the current power status and other things like that.
The benefit of NSOperation over a pure GCD approach is that operations can be cancelled. Once a block is committed to GCD it has to run no matter what.
If you want to encapsulate your HTTP requests in NSOperations you might be interested to know that someone has already done this for you. AFNetworking is one of the most widely regarded iOS networking stacks and uses NSOperations as its base to build on and as such is very easily multi threaded.
A good idea would be to try and encapsulate your parsing code into an NSOperation and then as your network request operations return you can create parsing operation instances and put them on another queue for processing in the background.

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.

Which tasks are more suitable to NSOperation than GCD? [duplicate]

This question already has answers here:
NSOperation vs Grand Central Dispatch
(9 answers)
Closed 9 years ago.
Which tasks would be better suited to using NSOperation as opposed to using GCD when programming for the iPhone?
To me they seem to do the same thing. I can't see the strengths and weaknesses one has over the other.
NSOperation is built on top of GCD, so the question is more about whether you use NSOperation or pass a block directly to GCD.
An NSOperation is bulky and needs more boiler-plate codes to set it up, but it has a lot more functionality. You can create the same NSOperation subclass in various parts of your code and put them into the queue and run it.
Passing a block to GCD by e.g. dispatch_async is quick and disposable. You typically don't reuse a block anywhere else; you just set up a block which is executed only at that point of the code, passes it to the GCD or other APIs, and quickly go on.
So each has its merits.
Apparently, NSOperationQueue is built on GCD as of iOS 4; the docs just haven't been updated. Check this posting by an Apple employee here: https://devforums.apple.com/message/352770 (You may need to create an account) So, you should follow Mike Abdullah's advice and use the simplest API for the task at hand. dispatch_async is lower level, usually C-type stuff (but not limited to), and is good for one-shot and sequential type deals (fire this block on this queue, FTW). NSOperationQueues are higher level, Objective-C stuff, and are good if you are adding a lot of operations at various points in your code, and/or need to manage concurrency, priorities and dependencies. At least that's how I use them.
As always with such questions, use the simplest API available. Measure if it's a performance problem and then reevaluate if needed.
One thing that I don't believe has been mentioned here is that NSOperations can be cancelled during execution, whereas a block is guaranteed to complete once execution has begun. Having said that, a GCD queue can be suspended (dispatch_suspend()), so that any blocks following the currently executing blocks will not be executed.

Resources