mach_absolute_time 使用

  今天看荣哥时间常用函数封装里有个不常见的函数 ,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
", time);
        
        time = BNRTimeBlock(^{
            for (int i = 0; i < LOOPAGE; i++) {
                [thing1 isEqualToString: thing2];
            }
        });
        printf ("isEqualToString: time: %f
", 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;
}
从〇开始,回到〇
原文地址:https://www.cnblogs.com/zpsoe/p/6994811.html