標籤:style 使用 os io 資料 for 2014 ar
前一段進行網路基礎庫構建的時候,網路發送的加密組包以及網路返回的回調解包處理都是在單獨的主線程處理。 跟蹤程式的時間發現這部分耗時還挺大,於是決定使用多執行緒,至少不應該使用主線程。
一直以來網上都在強調多線程的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)funcint 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了。通過這樣的方式,主線程僅僅關心自己的介面邏輯處理,將它從繁重的資料解析工作中解脫了出來,提升了效率。