前一段进行网络基础库构建的时候,网络发送的加密组包以及网络返回的回调解包处理都是在单独的主线程处理。 跟踪程序的时间发现这部分耗时还挺大,于是决定使用多线程处理,至少不应该使用主线程。
一直以来网上都在强调多线程的dispatch的妙用,自己仅仅是会用而没有实际测试过它的性能。今天将上次测试的结果发出来,说实话dispatch的多线程效率确实很高,跟cpu的核心数有很多关系。
测试思想:
使用一个自己写的耗时函数,让其执行一次所需要的时间进行记录。然后使用dispatch_global_queue进行执行4,6,8,10遍所耗的时间进行记录,来得到所花费的时间。基本代码非常简单,如下:
// // main.m // ThreadTest // // Created by lipeng on 14-7-23. // Copyright (c) 2014年 com.hollance. All rights reserved. // #import <Foundation/Foundation.h> #include <sys/time.h> #define REPEAT_TIMES 6 /* 可以看出自己的电脑的是几核的。 按道理说重复四次应该是4倍的时间,但是由于是双核的cpu,因此只需要两倍的时间。 */ typedef void*(*workFunc)(void) ; #define SetFunc(func) #func, (workFunc)func int getTime(char* identify, workFunc func) { struct timeval tv_begin, tv_end, tv_diff; gettimeofday(&tv_begin, NULL); func(); gettimeofday(&tv_end, NULL); timersub(&tv_end, &tv_begin, &tv_diff); long timeCost = tv_diff.tv_sec*1000 + tv_diff.tv_usec/1000; printf("%20s cost %10ld millseconds\n", identify, timeCost); return 0; } int costTimeFunc() { double m = 1.2, j = 3.4, k = 5.87; for (int i = 0; i < 3*3000000; ++i) { j = m * k * m; k = m * j * k; m = k * j * k; k = i * j * m; } return 0; } void testOneThread() { costTimeFunc(); } void testTwoThread() { dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(globalQueue, ^{ dispatch_apply(REPEAT_TIMES, globalQueue, ^(size_t index) { costTimeFunc(); }); }); } int main(int argc, const char * argv[]) { @autoreleasepool { for (int i = 0; i < 10; ++i) { getTime(SetFunc(testOneThread)); getTime(SetFunc(testTwoThread)); } } return 0; }
通过修改#define的 Repeat_times可以测试重复不同次数所花费的时间。测试结果发现当cpu是双核的时候,基本上时间会减少一半,cpu是四核的时候,时间大约是1/4。不过在i5双核上时间也是1/4,这是因为i5是双核四线程的,每一个核心可以同时两个线程在跑。这也间接印证了dispatch_global_queue的效率之高。
因此对于网络请求的处理还是采用dispatch_global_queue比较好,这样既避免了主线程的阻塞,同时对于多个同时发送的请求的返回处理效率会提高一些。在request的返回回调中首先用global_queue对结果进行预处理,拆包,解密,解析成数据model,然后将最后解析完地内容dispatch给主线程就OK了。通过这样的方式,主线程仅仅关心自己的界面逻辑处理,将它从繁重的数据解析工作中解脱了出来,提升了效率。
object-c编程tips-global_queue的一个小测试
时间: 2024-10-22 06:03:18