I have a XML in my App bundle. I am parsing this XML file. I parsed this XML using NSXMLParser and using following ways:
- running the whole code serially on main thread
-
Using dispatch queues (GCD):
2.1 Creating my own dispatch queue using dispatch_queue_create
2.2 using global queue with High Priority dispatch_get_global_queue
2.3 using global queue with Low Priority
2.4 using global queue with Background Priority
-
using
NSOperationQueue
I checked the performance and total time taken in execution of parsing the XML file and found really weird (or may be correct) results.
Following are the codes for above mentioned Parsing ways:
-
Serial execution on main thread – Execution time 34 msec.
BOOL success = [conf parseXMLFile:[[NSBundle mainBundle] pathForResource:@"Configuration" ofType:@"xml"] didFailWithError:&error]; if (success) { DLog(@"Parsing Complete"); } else DLog(@"Parse error %@",[error description]);
2.1 Using dispatch_queue_create – Execution time 68 msec.
dispatch_queue_t backgroundQueue = dispatch_queue_create("BackQueue", NULL);
dispatch_async(backgroundQueue, ^{
NSError *error = nil;
BOOL success = [conf parseXMLFile:[[NSBundle mainBundle] pathForResource:@"Configuration" ofType:@"xml"] didFailWithError:&error];
if (success) {
DLog(@"Parsing Complete");
}
else
DLog(@"Parse error %@",[error description]);
});
dispatch_release(backgroundQueue);
2.2 using global queue with High Priority dispatch_get_global_queue – Execution time – 74 msec
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(backgroundQueue, ^{
NSError *error = nil;
BOOL success = [conf parseXMLFile:[[NSBundle mainBundle] pathForResource:@"Configuration" ofType:@"xml"] didFailWithError:&error];
if (success) {
DLog(@"Parsing Complete");
}
else
DLog(@"Parse error %@",[error description]);
});
dispatch_release(backgroundQueue);
2.3 Similarly as 2.2 Using global queue with LOW Priority DISPATCH_QUEUE_PRIORITY_LOW – Execution time – 72 msec
2.4 Similarly as 2.2 Using global queue with BACKGROUND Priority DISPATCH_QUEUE_PRIORITY_BACKGROUND – Execution time – 37 msec
2.5. Using NSOperationQueue (subclassing the NSOperation) – Execution time – 36 msec
Can anyone help me figure out these execution times and why are they so strange (or am I missing something). Why I am getting the best performance with method 1.
Why is DISPATCH_QUEUE_PRIORITY_BACKGROUND giving better performance than HIGH.
Why is NSOperationQueue giving better results than GCD?
Update:
I tested the various dispatch and operation queues for for two scenarios:
Invoke a single job that repeatedly parse a large (725kb) XML file 100 times in a single operation; and
Queue 100 operations to parse the same very large XML file one time each.
My results (measured in seconds) on my iPhone 5 were as follows:
For first scenario:
For my second scenario:
So I draw two fairly unsurprising conclusions from this:
For a computationally intensive background operation at the very least, there did not appear to be much variation between the various concurrent background techniques;
When breaking a task into multiple operations, the concurrent background operations (
NSOperationQueue, GCD global queues) enjoyed a performance advantage over the serial operations.I’m not suggesting, though, that a device under resource contention might not exhibit different behavior in terms of scheduling (notably GCD global queue types, see
dispatch_queue_priority_t, would affect the scheduling of operations with other concurrent operations queued on the device). I’m only trying to demonstrate empirically that the various queues are not significantly more or less efficient than each other. Having said that, I personally wouldn’t useDISPATCH_QUEUE_PRIORITY_HIGHin my apps as I assume that would have the possibility of affecting core iOS functionality.Also, in the interest of full disclosure, I should admit that I’m focusing on material performance differences. It is quite possible that one mechanism or another might offer performance differences measured in msec. When I’m considering different approaches for background performance, I’m definitely more focused on user-observable performance differences.
Original Answer:
I invoked my
parseManyTimes(which repeatedly parses a large XML file) from the main queue:Via
NSOperation:Via global queues on GCD:
and
and
and via a GCD serial queue:
and the results did not differ significantly from each other (all between 32.2 and 32.5 seconds each). My parsing routine is:
I ran this on an iPad on a 725kb XML file. Clearly, the way I’ve structured this, with a very time consuming process, it will tend to was out any negligible variance in how the various queues are dispatched, but rather focus on the background operation. By it doesn’t raise any concerns (for me at least) in material performance issues in the various techniques.
The results were: