2010-08-22 43 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