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\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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM