由于项目的性能问题,我制作了以下测试程序(甚至使用了不同的变量进行完整性检查):
int main()
{
struct tm *timeinfo;
time_t rawtime;
clock_t begin, end, begin1, end1,begin2,end2;
double time_spent;
begin = clock();
for (int i = 0; i < 1000000; i++){
time ( &rawtime );
timeinfo = localtime(&rawtime);
}
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("Time elapsed using localtime() : %fs\n", time_spent);
//--------------------------------
begin1 = clock();
for (int i = 0; i < 1000000; i++){
time ( &rawtime );
timeinfo = gmtime(&rawtime);
}
end1 = clock();
time_spent = (double)(end1 - begin1) / CLOCKS_PER_SEC;
printf("Time elapsed using gmtime() : %fs\n", time_spent);
//--------------------------------
begin2 = clock();
for (int i = 0; i < 1000000; i++){
time ( &rawtime );
localtime_r( &rawtime, timeinfo);
}
end2 = clock();
time_spent = (double)(end2 - begin2) / CLOCKS_PER_SEC;
printf("Time elapsed using localtime_r() : %fs\n", time_spent);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到的结果很奇怪,localtime 花费了大约 24 倍的时间,localtime_r() 函数似乎比 localtime() 花费的时间少,但仍然比 gmtime() 多很多:
Time elapsed using localtime() : 0.958033s
Time elapsed using gmtime() : 0.038769s
Time elapsed using localtime_r() : 0.860276s
Run Code Online (Sandbox Code Playgroud)
我用 gcc 5 和 4.x 版本编译它,我用过 linux Mint(更新到今天)和 CentOS5。并且已经在不同的物理机上进行了测试,性能差异是相似的。
为什么会有如此(巨大)的性能差异?
如果您在下面运行此代码perf record,然后执行,perf report您会注意到每次迭代都会localtime调用getenv("TZ")。而gmtime没有。
查看glibc确认调用图的源代码:
gmtime
__tz_convert(, 0, )
tzset_internal(0, 1)
mktime
__tz_convert(, 1, )
tzset_internal(1, 1)
getenv("TZ")
Run Code Online (Sandbox Code Playgroud)
查看,
和 的
glibc源代码。localtimegmtime__tz_convert
perf report:
Samples: 78K of event 'cycles:u', Event count (approx.): 21051445406
Children Self Samples Command Shared Object Symbol ?
+ 99.48% 0.59% 349 test test [.] main ?
+ 99.48% 0.00% 0 test libc-2.23.so [.] __libc_start_main ?
+ 99.48% 0.00% 0 test test [.] _start ?
+ 98.02% 7.07% 4208 test libc-2.23.so [.] __tz_convert ?
- 24.51% 23.87% 20812 test libc-2.23.so [.] getenv ?
- 23.87% _start ?
__libc_start_main ?
main ?
__tz_convert ?
getenv ?
+ 0.64% getenv ?
+ 22.41% 12.75% 9877 test libc-2.23.so [.] __tzfile_compute ?
+ 15.49% 15.49% 8025 test libc-2.23.so [.] __offtime ?
+ 12.72% 6.28% 5476 test libc-2.23.so [.] __tzfile_read ?
+ 9.66% 3.54% 3086 test libc-2.23.so [.] __tzstring ?
+ 8.36% 1.40% 1221 test libc-2.23.so [.] __strdup ?
+ 7.68% 3.38% 2946 test libc-2.23.so [.] free ?
+ 5.98% 3.07% 2682 test libc-2.23.so [.] malloc ?
+ 4.96% 0.68% 611 test libc-2.23.so [.] __xstat64 ?
+ 4.30% 4.30% 3750 test libc-2.23.so [.] _int_free ?
+ 4.28% 4.28% 3731 test [kernel.kallsyms] [k] entry_SYSCALL_64 ?
+ 4.08% 4.08% 3564 test libc-2.23.so [.] strlen ?
+ 3.64% 3.64% 3168 test libc-2.23.so [.] __memcmp_sse2 ?
+ 2.91% 2.91% 2561 test libc-2.23.so [.] _int_malloc ?
+ 1.25% 1.25% 1094 test libc-2.23.so [.] __memcpy_sse2 ?
+ 0.68% 0.68% 587 test libc-2.23.so [.] localtime ?
0.26% 0.26% 222 test libc-2.23.so [.] 0x000000000001f910 ?
0.18% 0.18% 37 test test [.] gmtime@plt ?
0.15% 0.15% 126 test test [.] localtime@plt ?
0.11% 0.11% 23 test libc-2.23.so [.] gmtime ?
0.01% 0.01% 6 test [kernel.kallsyms] [k] __irqentry_text_start ?
0.00% 0.00% 3 test ld-2.23.so [.] _dl_lookup_symbol_x ?
0.00% 0.00% 5 test ld-2.23.so [.] do_lookup_x ?
0.00% 0.00% 2 test ld-2.23.so [.] _dl_relocate_object ?
0.00% 0.00% 1 test libc-2.23.so [.] 0x000000000001f8e8 ?
0.00% 0.00% 1 test ld-2.23.so [.] strlen ?
0.00% 0.00% 1 test ld-2.23.so [.] _dl_debug_initialize ?
0.00% 0.00% 1 test ld-2.23.so [.] _dl_start ?
0.00% 0.00% 1 test [kernel.kallsyms] [k] page_fault ?
0.00% 0.00% 6 test ld-2.23.so [.] _start
Run Code Online (Sandbox Code Playgroud)