6
votes

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:

screenshot

..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

2
Really good post on this topic answered by some apple developers: devforums.apple.com/message/37677 .... still doesn't quite answer my question about the asyn calling the sync method in the stack trace though. I'll ask there too. - bandejapaisa
It's hard to tell what your question is. It sounds like you're asking whether you should use sendAsynchronousRequest:queue:completionHandler: or sendSynchronousRequest:returningResponse:error: on a background thread, but you don't care about the non-performance-related benefits of using the async API. Can you clarify? - Christopher Pickslay
Well, my question really boils down to the screen shot. We're told not to use sendSynchronous, and advised to use sendAsynchronous. But it appears that sendAsync is calling sendSync. Can anyone confirm this behaviour or is there something more subtle, or obvious that i'm missing. Also, I still had a load of threads created using async over sync, when I expected i wouldn't. - bandejapaisa
You're told not to use SendSynchronous on the main thread, because it will block. As to what the framework does behind the scenes, I wouldn't base my design decisions on it, Apple can and has changed implementations before. - Eric
@Eric, that's right. But my post is about using sednSync using dispatch_async, which creates a background thread. So it's not on the main thread. I'm not making any design decision based on this stack trace. - bandejapaisa

2 Answers

0
votes

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.

0
votes

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!