Objective-C 中如何測量代碼的效率

背景

在我們編程的時候,可能經(jīng)常會有一些疑問:?

* 我們寫的某個方法的執(zhí)行效率是多少??

* 方法 A 和 方法 B 哪個更快?

因此,我們不可避免的要用到一些方法來計算代碼的執(zhí)行效率。計算代碼的執(zhí)行效率可以使用的API有:?

* NSDate?

* CFAbsoluteTimeGetCurrent?

* CACurrentMediaTime?

* dispatch_benchmark

NSDate

看到NSDate,大家應該都能想到怎么使用吧。為了更直觀一點,我還是使用代碼片段來演示好了:

NSTimeInterval startTime = [[NSDate new] timeIntervalSinceReferenceDate];NSLog(@"斐波那契數(shù):%d",fibonacci(10)) ;NSTimeInterval endTime = [[NSDate new] timeIntervalSinceReferenceDate];NSLog(@"耗時:%f", endTime - startTime);

上面是一段 C與OC混合的代碼片段,計算斐波那契數(shù)列計算第10個數(shù)的值需要消耗的時間。

利用NSDate 來計算運行效率:代碼段運行前記錄一次時間,運行后記錄一次,然后比較時間差。?

時間的單位是?秒

CFAbsoluteTimeGetCurrent

利用CFAbsoluteTimeGetCurrent 主要是利用CFAbsoluteTimeGetCurrent()函數(shù)來獲取當前的絕對時間。同樣的我也是用代碼片段來演示:

CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();NSLog(@"斐波那契數(shù):%d",fibonacci(10)) ;CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();NSLog(@"耗時:%f",endTime - startTime);

利用CFAbsoluteTimeGetCurrent 來計算運行效率:代碼段運行前記錄一次時間,運行后記錄一次,然后比較時間差。?

時間的單位是?秒。

看到這里可能會有疑問CFAbsoluteTimeGetCurrent()是如何獲取時間的呢??

我們追蹤進去查看代碼,就會有答案了,這是源碼:

從CFTimeInterval的定義和注釋可以看出,CFAbsoluteTimeGetCurrent(void)返回的時間就是當前時間相對與reference date的時間。?

CFTimeInterval?是對double 的重命名。?

而NSTimeInterval?也是對double 的重命名。?

它們之間的關系就可想而已了!?

CFAbsoluteTimeGetCurrent()?其實等價于?[[NSDate new] timeIntervalSinceReferenceDate]?。

CACurrentMediaTime

利用CACurrentMediaTime主要是利用CACurrentMediaTime()函數(shù)來計算時間。?

還是先用示例來演示用法:

CFTimeInterval startTime = CACurrentMediaTime();NSLog(@"斐波那契數(shù):%d",fibonacci(10)) ;CFTimeInterval endTime = CACurrentMediaTime();NSLog(@"耗時:%f",endTime - startTime);

計算執(zhí)行效率時間上依然是:代碼段運行前記錄一次時間,運行后記錄一次,然后比較時間差。?

時間的單位是?秒。

跟蹤查看源碼中對CACurrentMediaTime()的定義

/* Returns the current CoreAnimation absolute time. This is the result of?* calling mach_absolute_time () and converting the units to seconds. */

CA_EXTERN CFTimeInterval CACurrentMediaTime (void)

? ? __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);

可以看出CACurrentMediaTime() 是對mach_absolute_time()的封裝。返回的是CoreAnimation 中的當前時間。

dispatch_benchmark

dispatch_benchmark 是libdispatch(Grand Central Dispatch)的一部分。但嚴肅地說,這個方法并沒有被公開聲明,所以我們必須要自己聲明:

extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));

第二個參數(shù)是執(zhí)行的代碼片段block。?

第一個參數(shù)是執(zhí)行的次數(shù)(即運行block 的次數(shù))。

uint64_t t = dispatch_benchmark(1000000, ^{

? ? NSLog(@"斐波那契數(shù):%d",fibonacci(10)) ;

? });NSLog(@"耗時: %llu ns", t);

警告:?

這里寫的是我自己的理解,但是不一定正確,如果你有比較確切的資料或者不同的理解,麻煩告知我,萬分感謝!?

dispatch_benchmark 應該是通過計算多次執(zhí)行某代碼片段的總時間,通過多次運行的總時間除以迭代運行的次數(shù)來計算一次運行的時間,以減小單次運行的誤差。?

dispatch_benchmark(size_t count, void (^block)(void))返回的就是單次運行代碼段的時間。

關于dispatch_benchmark1的更多的文章,我們可以去文章末的資料中查看。

區(qū)別

1、它們所屬的框架不同。

NSDate 來自Foundation框架,只需要#import,就可以使用了。CFAbsoluteTimeGetCurrent 來自CoreFoundation框架,而Foundation框架是包含CoreFoundation框架的。

CACurrentMediaTime 來自QuartzCore框架,而UIKit框架是包含了QuartzCore框架的。

dispatch_benchmark 來自?libdispatch(G C D)庫,而Foundation框架已包含了libdispatch庫。

2、參考時間不同。?

NSDate 和 CFAbsoluteTimeGetCurrent 是通過ReferenceDate來計算相差的秒值。與服務器的時間有關系。?

而CACurrentMediaTime() 是封裝的mach_absolute_time(),mach_absolute_time() 是基于內(nèi)建時鐘的,能夠更精確更原子化地測量,并且不會因為外部時間變化而變化(例如時區(qū)變化、夏時制、秒突變等)。?

dispatch_benchmark的時間計算方式未知(推測不是根據(jù)參考時間計算)。

3、時間的精度不同?

NSDate、CFAbsoluteTimeGetCurrent、CACurrentMediaTime計算出來的時間精度都是秒。?

而dispatch_benchmark 的時間精度是納秒。

最后提醒

因為從操作系統(tǒng)本身的一切基本因素都是可變性非常強的,性能應該通過大量的試驗來測量。對于大多數(shù)應用來說,樣本數(shù)量在 105?到 108?之間是合理的。?

所以我們應該運行要執(zhí)行的代碼段 105?到 108次,再來求平均值。

更多關于dispatch_benchmark的介紹。?

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容