今天看荣哥时间常用函数封装里有个不常见的函数 ,mach_absolute_time() ,经查询后感觉是个不错的函数,网上关于这个函数搜索以后简单整理来一下。
什么事Mach?
时间例程依赖于所需要测量的时间域。 某些情况下使用诸如clock() 或 getrusage()函数来做简单的数学运算就足够了。如果时间例程将用于实际开发框架之外,可移植性就很重要来。
mach_absolute_time 是一个CPU/总线依赖函数,返回一个基于系统启动后的时钟"嘀嗒"数。在macOS上可以确保它的行为,并且,它包含系统时钟所包含的所有时间区域。其可获取纳秒级的精度。
使用mac_absolute_time时需要考虑两个因素:
1.如何获取当前的Mach绝对时间。
2.如何将其转换为有意义的数字。
* 获取mach_absolute_time非常简单
#include <stdint.h> uint64_t start = mach_absolute_time();//是纳秒 uint64_t stop = mach_absolute_time();
这样我们就可以得到两个值,即可获得两个时间的时间差。
* 讲mach_absolute_time时间差转换为秒数,这稍微复杂点了,因为我们需要获得mach_absolute_time所基于的系统时间基准。
#include <stdint.h> #include <mach/mach_time.h> double subtractTimes(uint64_t endTime,uint64_t startTime) { uint64_t difference = endTime - startTime; static double conversion = 0.0; if(conversion == 0.0) { mach_timebase_info_data_t info; kern_return_t err = mach_timebase_info(&info); //convert the timebase into seconds if(err ==0) { conversion = 1e-9 * (double) info.numer / (double)info.denom; } return conversion * (double)difference; }
这里最重要的是调用mach_timebase_info. 我们传递一个结构体以返回时间基准值。最后,一旦我们获取到了系统的时间心跳,我们便能够生成一个转换因子。通常,转换是通过分子(info.numer)除以分母(info.denom).这里乘以一个1e-9来获取秒数。最后,我们获取两个时间的差值,并乘以转换因子,便得到真实的时间差。
网速找的一个比较好的例子:
#import <mach/mach_time.h>
double machTimeToSecs(uint64_t time)
{
mach_timebase_info_data_t timebase;
mach_timebase_info(&timebase);
return(double)time *(double)timebase.number / (double)timebase.denom / 1e9;
}
-(void)profileDoSometing
{
uint64_t begin = mach_absolute_time();
[self dosomething];
uint64_t end = mach_absolute_time();
NSLog(@"Time taken to doSomething %g s",machTimeToSecs(end - begin));
}
-(void)dosomething
{
for(int i = 0;i < 10000;i++){
NSLog(@"test");
}
}
荣哥封装的是这样的:
+ (uint64_t)getStartTime { uint64_t nStartTick = mach_absolute_time();// 单位事纳秒 return nStartTick; } + (double)getDurationSecondTime:(uint64_t)nStartTick { uint64_t nTotalTick = mach_absolute_time()-nStartTick; double fTotalSecond = [self machTimeToSecs: nTotalTick]; return fTotalSecond; } + (double)machTimeToSecs:(uint64_t)time { mach_timebase_info_data_t timebase; mach_timebase_info(&timebase); return (double)time*(double)timebase.numer/(double)timebase.denom/1e9;//ns 转换为 s }
使用时候,直接调用getStartTime开始计时,调用getDurationSecondTime获得结束时间
网上还有一个通过该函数测某方法运行时间,以便代码优化,感觉也是不错的,记录下来以便备用。
#import <Foundation/Foundation.h> #import "TimeOperations.h" #define LOOPAGE 10000000 CGFloat BNRTimeBlock (void (^block)(void)) { mach_timebase_info_data_t info; if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0; uint64_t start = mach_absolute_time (); block (); uint64_t end = mach_absolute_time (); uint64_t elapsed = end - start; uint64_t nanos = elapsed * info.numer / info.denom; return (CGFloat)nanos / NSEC_PER_SEC; } // BNRTimeBlock int main(int argc, const char * argv[]) { @autoreleasepool { CGFloat time; NSString *thing1 = @"hi"; NSString *thing2 = @"hello there"; time = BNRTimeBlock(^{ for (int i = 0; i < LOOPAGE; i++) { [thing1 isEqual: thing2]; } }); printf ("isEqual: time: %f\n", time); time = BNRTimeBlock(^{ for (int i = 0; i < LOOPAGE; i++) { [thing1 isEqualToString: thing2]; } }); printf ("isEqualToString: time: %f\n", time); } return 0; }
CGFloat ComputeTimeBlock (void (^block)(void)) { mach_timebase_info_data_t info; if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0; uint64_t start = mach_absolute_time (); block (); uint64_t end = mach_absolute_time (); // 此时是纳秒 uint64_t elapsed = end - start; uint64_t nanos = elapsed * info.numer / info.denom; CGFloat test = (CGFloat)nanos / NSEC_PER_SEC; return test; } CGFloat ComputeTimeBlock2 (void (^block)(void)) { mach_timebase_info_data_t info; if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0; uint64_t start = CACurrentMediaTime(); // 此时是秒 block (); uint64_t end = CACurrentMediaTime(); uint64_t elapsed = end - start; return elapsed; }