gettimeofday 實現原理和優化

一、原理描述

https://blog.csdn.net/lqxandroid2012/article/details/51487547

二、問題描述

Easydarwin中大量使用gettimeofday來獲取系統時間,對系統性能造成了一定的影響。我們來做個測試: 
這裏寫圖片描述

While(1)
{
    Gettimeofday(&tv,NULL);
}
  •  

這裏寫圖片描述

每秒執行次數爲約3000w次;

三、我們來看看gettimeofday函數內核實現

參見:http://blog.csdn.net/russell_tao/article/details/7185588

四、my_gettimeofday()實現

static inline int getcpuspeed_mhz(unsigned int wait_us)
{
       u_int64_t tsc1, tsc2;
       struct timespec t;

        t.tv_sec = 0;
        t.tv_nsec = wait_us * 1000;

        rdtscll(tsc1);

        // If sleep failed, result is unexpected, the caller should retry
        if(nanosleep(&t, NULL))
                return -1;
         rdtscll(tsc2);
         return (tsc2 - tsc1)/(wait_us);
} 

int getcpuspeed()
{
        static int speed = -1;
         while(speed<100)
                speed = getcpuspeed_mhz(50*1000);
         return speed;
}

int my_gettimeofday(struct timeval *tv)
{
        u_int64_t tick = 0;

        // TSC偏移大於這個值,就需要重新獲得系統時間
        static unsigned int max_ticks = 80000000;
        rdtscll(tick);
        if(walltime.tv_sec==0 || cpuspeed_mhz==0 ||
                (tick-walltick) > max_ticks)
        {
                if(tick==0 || cpuspeed_mhz==0)
                {
                        cpuspeed_mhz = getcpuspeed();
                        max_ticks = cpuspeed_mhz*RELOAD_TIME_US;
                }
                //printf("gettimeofday again\n");
                gettimeofday(tv, NULL);
                memcpy(&walltime, tv, sizeof(walltime));
                rdtscll(walltick);
                return 0;
        }

        memcpy(tv, &walltime, sizeof(walltime));
        // if RELOAD_TIME_US is 1, we are in the same us, no need to adjust tv
#if RELOAD_TIME_US > 1
        {
                uint32_t t;
                t = ((uint32_t)tick) / cpuspeed_mhz;
                TIME_ADD_US(tv, t);//add 1 us
        }
#endif
        return 0;
}
  •  

通過休眠一段時間,然後檢查cpu TSC變化,來大概估算cpu時鐘頻率,然後每次調用my_gettimeofday時,通過宏,rdtscll獲取寄存器rdtsc寄存器的值,系統啓動後cpu的tick數,當然第一次要先獲取一下當前系統時間,gettimeofday。然後根據上面計算出來的cpu頻率,以及獲取到的cpu已經走過的tick數,計算出相對前面的gettimeofday時間的偏移,相加後得到當前系統時間。

備註:上面講過,由於通過休眠一段時間,統計cpu tick變化的方式統計的cpu頻率有一定誤差,因此。Cpu tick每走過80000000重新校驗一次,如果想要更高的精度,可以把這個值縮小。

五、優化後的測試效果

這裏寫圖片描述 
8000w+次每秒,性能提高了2-3倍。 
在EasyDarwin上測試,通過easypusher_file推送100路,經過my_gettimeofday優化後,cpu消耗降低8%左右。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章