localtime() 比 Linux 上的 gmtime() 性能问题多 24 倍
localtime() takes 24 times more than gmtime() performance issue on linux
由于项目的性能问题,我制作了以下测试程序(甚至使用不同的变量进行健全性检查):
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() : %fsn", 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() : %fsn", 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() : %fsn", time_spent);
return 0;
}
我得到的结果很奇怪,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
我用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")
请参阅localtime
的源代码glibc
, gmtime
和 __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
缓存
localtime
和gmtime
的部分工作。
因此,只有第一次调用这些函数之一才能完成真正的工作,即读取/etc/localtime
以获取本地时区。此操作也适用于gmtime()
,即使可能没有必要。
为了获得可靠的结果,请在第一次测量之前致电gmtime
或localtime
。那么这两个功能的性能应该是相似的。
相关文章:
- 在类中使用随机生成器时出现性能问题
- Qt OpenGL 渲染到纹理性能问题
- 剪辑性能问题
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- OpenCV - 基本操作 - 性能问题 [模式:发布]
- 使用 #define 进行跟踪日志记录以避免性能问题
- 在 Qt C++ 中在自定义项委托上绘制文本时的性能问题
- std::函数有性能问题,如何避免?
- 使用 const double* const 作为模板参数 - 代码性能问题
- 在C 中读取大型CSV文件性能问题
- MPI 二进制文件 I/O 基本功能和性能问题
- 如何修复macOS线程互斥锁性能缓慢的问题?
- 使用STD :: MAP在数据及其性能问题中查找重复项.我可以预先分配吗?
- C 功能性能问题
- 一维数组映射方式的性能差异问题
- 在C 性能问题中使用Getter返回地图
- 初始化每个班级成员时的性能问题
- 事件(开始,结束),1天的最大事件.C++ 中的性能问题
- 在X64模式下从C /CLI调用MASM PROC会产生意外的性能问题
- OpenGL:MESA3D屏幕上的软件渲染性能问题