繁体   English   中英

在Linux上,localtime()的性能是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()      : %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;
}

我得到的结果非常奇怪,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")

请参见localtimegmtime__tz_convert glibc源代码。

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     

工作的零部件localtimegmtime缓存。

因此,只有对这些功能之一的首次调用才能完成实际工作,即读取/etc/localtime以获取本地时区。 即使可能没有必要,也会对gmtime()执行此操作。

为了获得可靠的结果,请在首次测量之前致电gmtimelocaltime 这两个功能的性能应相似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM