Apple released Grand Central Dispatch with Mac OS X 10.6. GCD comes with asynchronous socket monitoring utilities that are written on top of the fast and efficient kqueue architecture. And while they were at it, they also rewrote the core of the CFNetworking stack (CFSocket) to tie into these GCD tools. But while they rewrote the underlying architecture of CFSocket, they did NOT change the exterior API's available to you and me. What this means is that Apple's CF/NS networking classes (CFSocket, CFStream, NSStream) are still RunLoop based, so if you want asynchronous notifications you'll need to add an observer to be invoked on some thread.
This runloop based architecture makes it more difficult to parallelize tasks. It also makes if more difficult if you want to write a server that can handle hundreds of clients simultaneously.
But this isn't the only the problem. Both kqueue's and GCD provide additional functionality that improves performance, and this functionality is hidden by Apple's current CF/NS networking API's. Let's consider reading data from a socket:
The old way to do it would be to poll the socket until you're notified there is data available to be read. But how much data is available? The poll doesn't tell you. You're just going to have to guess. If you guess too little, you'll end up invoking read more often. Which means more kernel calls, and a slower application. Guess too much, and you'll end up allocating larger than necessary buffers and wasting memory. Want to know exactly how much data is available? Technically there is a method for that. But now we're back at additional kernel calls, and we may as well invoke read multiple times.
Kqueues solve this problem. When you register to receive notifications of available data, the notification will tell you how much data is available to be read. Then you can slurp it all up in a single read, and go back to waiting for notifications. It's faster and more efficient.
Apple's runloop based socket API's don't tell us how much data is available to be read. Similar to a poll, they just tell us that data is available.
In addition to this, if you're writing a server and listening for incoming connections, a poll could tell you if there is an available connection ready to be accepted. But again, it doesn't tell you how many connections are pending. Kqueues provide this information.
GCDAsyncSocket is based on Apple's GCD socket tools, and thus it can take advantage of the features that kqueues provide.
So how does it perform?
To answer this question I've been porting CocoaHTTPServer to run atop GCDAsyncSocket. Preliminary benchmarks indicate a performance boost somewhere between 250% to 400% depending upon the amount of concurrent connections.
I'll be continuing the CocoaHTTPServer port this week. When it's finished, I'll post more detailed benchmarks. (With charts and graphs!)
Take a look at GCDAsyncSocket via the Google Code Page.