使用各种调度队列和NSOperationQueue处理执行时间和性能

我的应用程序包中有一个XML。 我parsing这个XML文件。 我使用NSXMLParser并使用以下方法分析了这个XML:

  1. 在主线程上串行运行整个代码
  2. 使用调度队列(GCD):

    2.1使用dispatch_queue_create创build我自己的分派队列

    2.2使用具有高优先级dispatch_get_global_queue的全局队列

    2.3使用低优先级的全局队列

    2.4使用具有背景优先级的全局队列

  3. 使用NSOperationQueue

我检查了执行parsingXML文件所花费的性能和总时间,发现真的很奇怪(或可能是正确的)结果。

以下是上述parsing方式的代码:

  1. 主线程上的串行执行 – 执行时间34毫秒。

     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使用dispatch_queue_create – 执行时间68毫秒

 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使用具有高优先级的全局队列dispatch_get_global_queue – 执行时间 – 74毫秒

 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与2.2一样使用低优先级的全局队列DISPATCH_QUEUE_PRIORITY_LOW – 执行时间 – 72毫秒

2.4与2.2一样使用具有背景优先级的全局队列DISPATCH_QUEUE_PRIORITY_BACKGROUND – 执行时间 – 37毫秒

2.5。 使用NSOperationQueue (inheritanceNSOperation) – 执行时间 – 36毫秒

任何人都可以帮我弄清楚这些执行时间,为什么他们很奇怪(或者我错过了什么)。 为什么我用方法1获得最佳性能?为什么DISPATCH_QUEUE_PRIORITY_BACKGROUND比HIGH性能更好。 为什么NSOperationQueue比GCD提供更好的结果?

更新:

我testing了两种情况下的各种调度和操作队列:

  1. 调用单个操作重复parsing大型(725kb)XML文件100次的单个作业; 和

  2. 队列100操作分别parsing同一个非常大的XML文件。

我的iPhone 5的结果(以秒为单位)如下:

  1. 对于第一种情况:

    主队列:18.7
     NSOperation:18.4
    全球高优先级队列:18.3
    全局默认优先级队列:18.4
    全球低优先级队列:18.4
    全球背景排队:18.5
    串行调度队列:18.3
    
  2. 对于我的第二个场景:

    主队列:18.7
     NSOperation:10.9
    全球高优先级队列:10.9
    全局默认优先级队列:10.8
    全局低优先级队列:10.8
    全局背景队列:11.0
    串行调度队列:18.5
    

所以我从中得出了两个相当不奇怪的结论:

  • 对于计算密集的背景操作,至less在各种并发背景技术之间似乎没有太大的变化;

  • 将任务分解为多个操作时,并发后台操作( NSOperationQueue ,GCD全局队列)比串行操作具有性能优势。

然而,我并不是build议资源争用下的设备在调度方面可能不会performance出不同的行为(特别是GCD全局队列types,请参阅dispatch_queue_priority_t会影响设备上排队的其他并发操作的调度)。 我只是试图通过实证来certificate,各个队列的效率并不显着。 话虽如此,我个人不会在我的应用程序中使用DISPATCH_QUEUE_PRIORITY_HIGH ,因为我认为这会影响核心iOSfunction。

另外,为了充分披露,我应该承认我关注的是材料性能的差异。 一种机制或另一种机制很可能提供以毫秒为单位的性能差异。 当我考虑不同的背景performance方法时,我肯定更关注用户可观察到的性能差异。


原始答案:

我从主队列中调用了parseManyTimes (它反复分析一个大的XML文件):

 [self parseManyTimes:@"Main queue"]; 

通过NSOperation

 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ [self parseManyTimes:@"NSOperation"]; }]; queue = nil; 

通过GCD全球排队:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self parseManyTimes:@"DISPATCH_QUEUE_PRIORITY_DEFAULT"]; }); 

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [self parseManyTimes:@"DISPATCH_QUEUE_PRIORITY_HIGH"]; }); 

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ [self parseManyTimes:@"DISPATCH_QUEUE_PRIORITY_LOW"]; }); 

并通过GCD串行队列:

 dispatch_queue_t dispatchQueue = dispatch_queue_create("org.rob.test", NULL); dispatch_async(dispatchQueue, ^{ [self parseManyTimes:@"dispatch_queue_create"]; }); 

结果没有显着差异(均在32.2和32.5秒之间)。 我的parsing程序是:

 - (void)parseManyTimes:(NSString *)type { NSDate *startDate = [NSDate date]; for (NSInteger i = 0; i < 100; i++) [self parse]; NSLog(@"%@: %.1f", type, [[NSDate date] timeIntervalSinceDate:startDate]); } - (void)parse { NSURL *url = [[NSBundle mainBundle] URLForResource:@"personnel" withExtension:@"xml"]; NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url]; parser.delegate = self; [parser parse]; } 

我在一个725kb的XML文件上运行这个iPad。 显然,我这样做的方式是非常耗时的,所以在各个队列的调度方面往往会忽略不计,而是关注后台操作。 因为在各种技术的材料性能问题上没有引起任何担忧(至less对我而言)。

结果是:

主队列:32.3
 NSOperation:32.2
 DISPATCH_QUEUE_PRIORITY_DEFAULT:32.4
 DISPATCH_QUEUE_PRIORITY_HIGH:32.3
 DISPATCH_QUEUE_PRIORITY_LOW:32.5
 dispatch_queue_create:32.3

各种默认并发队列的性能只是相对的。 “高”优先级意味着高于其他队列。 我期望你的综合基准当时没有什么事情发生,这就是为什么所有的队列看起来都是等价的。 如果您想要实际演示权重,请将一百个parsing操作一次排入每个并发队列,然后比较它们的执行时间。

还要注意,NSOperation使用默认优先级的并发队列来执行,所以你看到的性能基本上是一样的。 最好你只是测量NSOperation的开销,这是微小的。

在你最初的结果中,你看到了完全不同的计时。 那些测量的条件是什么? 例如,如果您在应用程序启动时执行此操作,则将XMLparsing转换为另一个线程或队列可能需要更长的时间,因为您的主线程和队列可能会与CPU时间竞争。 在这种情况下,更好的testing将是整体启动时间,这将certificate利用多核心的好处。