2010-08-22 80 views
13

我正在尋找iPhone的高分辨率時間碼,以便做一些表演時機。我想這樣寫代碼:適用於iPhone的高分辨率定時器?

HighResolutionTimer* myTimer = [[HighResolutionTimer alloc]init]; 
[myTimer start]; 
[self doSomeLengthyOperation]; 
NSLog(@"doSomeLengthyOperation took %f seconds", [myTimer elapsedTime]); 
+1

爲什麼不使用'getrusage()'?任何在C中工作的東西都可以在Objective-C中工作。 – 2010-08-22 04:59:43

+1

因爲有一個完美的可可方法可以做同樣的事情。 – lucius 2010-08-22 05:04:55

回答

26

查看mach/mach_time.h標題中的mach_absolute_time()。

請勿使用NSDate。當ntp做它的事情時,NSDate甚至不保證不會偶爾倒退。如果iOS設備漂移幾秒鐘,那麼當NTP糾正這個漂移時,你會看到時鐘突然倒退幾秒鐘,對於時間使用非常不利。mach_time使用計數器不曾經得到由NTP糾正,因此不能走回頭路,因此是更好的時機。)

+1

'NSDate'只返回一個自2001年1月1日以來的秒數。對於秒錶計時,負的時間不會發生,所以我看不需要將'mach_absolute_time()'帶入代碼的開銷 - [在這裏實現](http://stackoverflow.com/a/12553393/111307)。 – bobobobo 2012-09-23 15:52:15

+3

@bobobobo:設備自2001年1月1日以來的秒數偶爾會被NTP向後修正。因此,對於任何具有時鐘漂移的時鐘晶振,以及可以糾正漂移的網絡連接,它都可以是非單調的。 – hotpaw2 2012-09-23 18:03:20

+0

我結束了使用mach_absolute_time()。我發現了一個小班使用它,[這裏](http://zpasternack.blogspot.com/2012/07/high-resolution-timing-in-cocoa.html)。 – zpasternack 2012-09-23 19:08:43

5

使用NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]以在最後得到的開始時間,然後NSLog (@"Operation took %f seconds.", [NSDate timeIntervalSinceReferenceDate] - startTime);

+1

完美的作品,謝謝!我沒有意識到NSDate具有這種精度。 – zpasternack 2010-08-22 05:19:34

16

更好的選擇是CACurrentMediaTime()它使用mach_absolute_time()但其轉換爲CFTimeInterval(即時間,以秒爲一雙)給你。

+0

需要['#import '](https://stackoverflow.com/q/729094)。 – Pang 2017-08-10 08:34:19

8

下面是我使用mach_absolute_time()(基於計算方法shown hereNSDate)的時鐘計時器的答案。在準確性方面實際上是相同的。

馬赫版本

double machGetClockS() 
{ 
    static bool init = 0 ; 
    static mach_timebase_info_data_t tbInfo ; 
    static double conversionFactor ; 
    if(!init) 
    { 
    init = 1 ; 
    // get the time base 
    mach_timebase_info(&tbInfo) ; 
    conversionFactor = tbInfo.numer/(1e9*tbInfo.denom) ; // ns->s 
    } 

    return mach_absolute_time() * conversionFactor ; // seconds 
} 

double machGetClockDiffS() 
{ 
    static double lastTime = 0; 

    double currentTime = machGetClockS() ; 

    double diff = currentTime - lastTime ; 

    lastTime = currentTime ; // update for next call 

    return diff ; // that's your answer 
} 

NSTimeInterval版本

double getClockS() 
{ 
    return [NSDate timeIntervalSinceReferenceDate] ; // NSTimeInterval is always specified in seconds 
} 

double getClockDiffS() 
{ 
    static double lastTime = 0 ; 

    double currentTime = getClockS() ; 

    double diff = currentTime - lastTime ; 

    lastTime = currentTime ; // update for next call 

    return diff ; // that's your answer 
} 

結果:

注意在這兩個分辨率纔是真的好。

 

IOS SIMULATOR, running frame rate counts (in milliseconds (*1000.0)) 

MACH_ABS_TIME/NSTimeIntervals 
58.557001/58.552980 
40.558007/40.562987 
52.207822/52.200019 
33.742197/33.742011 
38.498912/38.504004 
48.872679/48.868001 
45.012602/45.011997 
57.858432/57.865977 
25.044615/25.038004 


IPAD HARDWARE SAMPLINGS: 
33.415041/33.416033 
33.240167/33.239007 
33.357542/33.357978 
33.302833/33.302009 
33.506750/33.509016 
33.582250/33.582985 
33.233958/33.232987 
33.239042/33.237994 

*如果你看到這篇文章的編輯歷史,你可以看到在double的地方使用float的危險!

+0

你忘了添加init = true;在machGetClockS()中。 – 2013-10-09 23:12:45

+0

@Andrew史密斯好點!固定。 – bobobobo 2013-10-09 23:46:34

+0

時間分辨率不是一個很好的測試,因爲你測試時沒有wireshark監控任何NTP網絡連接,有時真的會混淆NSDate結果。 – hotpaw2 2015-05-04 18:25:44