前面的博文陆续讨论了异步执行系统中, 主要以测算任务执行时间为目的的高性能时间服务get_tick_count,并特别强调,get_tick_count并不适合需要知道确切时间(即某年某月某时某刻...)的场合。但这类场合仍然是客观存在的,其中典型的Case是写系统日志。有过大型Server开发经验的同仁不会怀疑日志对于这类系统的重要性,日志可能被用于多种目的:系统行为跟踪,错误诊断,安全审计,以及形形色色的管理,维护及分析等目的。开发和支持总是希望日志越细越好,但不幸的是写日志并不是“免费午餐”,往往会消耗掉相当可观的Server资源。 有效的设计和谨慎的使用对于日志服务都很非常重要--这是一个专题,我们会在后面深入讨论。这里只对日志服务中频繁使用的本地时间服务(某年某月某日某时某刻...)做些评测及分析。先测试一下系统本地时间服务的效率。
测试条件:Windows XP 2002--Intel(R) Celeron(R) CPU 2.66GHz
Linux 2.4.18-14--Intel(R) Celeron(R) CPU 2.00GHz
调用次数:1000万次
--Linux--
测试代码:
void get_localtime(struct tm *ptm)
{
time_t cur=time(0);
localtime_r(&cur, ptm);
}
int main(int argc, char **argv)
{
struct timeval tv1,tv2,tv_diff;
struct tm tm_var;
gettimeofday(&tv1, 0);
for(int i=0;i<10000000;++i) get_localtime(&tm_var);
gettimeofday(&tv2,0);
printf("elapsed time:%d/n",diff_of_timeval_tc(tv1,tv2));
return 0;
}
测试结果:23000ms
--Windows--
测试代码:
void get_localtime(struct tm *tblock)
{
time_t timer=time(0);
*tblock=*(localtime(&timer));
}
int main(int argc, char* argv[])
{
time_t timer;
struct tm tblock;
long tc1,tc2;
tc1=::GetTickCount();
for(int i=0;i<10000000;++i)
{
get_localtime(&tblock);
}
tc2=::GetTickCount();
printf("elapsed:%lu/n", tc2-tc1);
return 0;
}
测试结果:10700ms
--Windows2--
Windows下有更简单的函数调用可得到毫秋级的当前时间GetLocalTime(LPSYSTEMTIME lptm)
测试代码:
int main(int argc, char* argv[])
{
long tc1,tc2;
tc1=::GetTickCount();
SYSTEMTIME stm;
for(int i=0;i<10000000;++i)
{
::GetLocalTime(&stm);
}
tc2=::GetTickCount();
printf("elapsed:%lu/n", tc2-tc1);
return 0;
}
测试结果:3840ms
结论:和前面讨论的get_tick_count相比,localtime是个成本相当高昂的服务,其中Windows表现仍然比Linux好,case1性能约高出一倍,但其时间精度受time()的限制,只能到秒级,Case2可以到毫秒级,且效率更高,比Linux约高出5倍。考虑到高性能服务器通常会采用Linux,故在Linux上实现一个高效的localtime版本对于写日志这类需要频繁调用该服务的场合是非常必要的,而Windows下更多会作为Client端使用,况且GetLocalTime已经具有较高的效率,因此,本项目在Windows下的本地时间服务将直接调用GetLocalTime,而不再提供高性能版实现