I noticed that my application is connecting to remote resources way slower than web browsers, or cURL and decided to do some digging.
I've been using NSURLSession sessionWithConfiguration:delegate:
to handle server responses, and decided to try instead using NSURLSession dataTaskWithRequest:completionHandler:
. The test methods are below:
-(void)connectWithDelegate:(NSString *)url
{
semaphore = dispatch_semaphore_create(0);
session = [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration]
delegate: self
delegateQueue: nil];
NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: url]
cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: 60.0];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest: req];
[dataTask resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
- (void)connectWithCompletionHandler:(NSString *)url
{
semaphore = dispatch_semaphore_create(0);
session = [NSURLSession sharedSession];
NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: url]
cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: 60.0];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:req completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error){
if (!error)
dispatch_semaphore_signal(semaphore);
}];
[dataTask resume];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
Running these tests repeatedly with a range of different network conditions, the connectWithCompletionHandler:
method consistently outperforms connectWithDelegate:
. On slow connections it can be as much as 6 times faster to return.
The full test code can be found here.
Running this test over 20 iterations on a 5Mb/s link with 50 ms latency yields an average connection time of 0.6 seconds for connectWithCompletionHandler:
and 2 seconds for connectWithDelegate:
What accounts for the difference in response time between these two methods...?