测试mktime和localtime_r性能及优化方法
2017-01-22 16:23
357 查看
// 测试mktime和localtime_r性能及优化方法 // // 编译方法:g++ -g -o x x.cpp或g++ -O2 -o x x.cpp,两种编译方式性能基本相同。 // // 结论: // 1) 环境变量TZ和isdst均不影响localtime_r的性能(第一次调用了除外) // 2) 环境变量TZ严重影响localtime的性能 // 3) 环境变量TZ和isdst均会严重影响mktime的性能 // *4) 注意mktime的参数即是输入参数也是输出参数,它会修改isdst值 // *5) 另外需要注意localtime_r为非信号安全函数, // 不能在信号处理过程中调用,否则可能发生死锁等问题 // // 64位机器性能数据(与32位CPU不同): /* $ ./x 1000000 test: localtime ... TZ is NULL: 2457ms TZ is empty: 172ms TZ is Asia/Shanghai: 173ms test: localtime_r ... TZ is NULL and isdst=1: 125ms TZ is NULL and isdst=0: 125ms TZ is NULL and isdst=-1: 125ms TZ is NULL and isdst undefined: 125ms TZ is empty and isdst=1: 125ms TZ is empty and isdst=0: 125ms TZ is empty and isdst=-1: 125ms TZ is empty and isdst undefined: 127ms TZ is Asia/Shanghai and isdst=1: 126ms TZ is Asia/Shanghai and isdst=0: 125ms TZ is Asia/Shanghai and isdst=-1: 125ms TZ is Asia/Shanghai and isdst undefined: 125ms test: mktime ... TZ is NULL and isdst=1: 635841ms TZ is NULL and isdst=0: 2583ms TZ is NULL and isdst=-1: 2596ms TZ is NULL and isdst undefined: 2579ms TZ is empty and isdst=1: 122377ms TZ is empty and isdst=0: 229ms TZ is empty and isdst=-1: 230ms TZ is empty and isdst undefined: 229ms TZ is Asia/Shanghai and isdst=1: 122536ms TZ is Asia/Shanghai and isdst=0: 228ms TZ is Asia/Shanghai and isdst=-1: 230ms TZ is Asia/Shanghai and isdst undefined: 228ms */ // 32位机器性能数据(与64位CPU不同): /* $ ./x 1000000 test: localtime ... TZ is NULL: 1445ms TZ is empty: 252ms TZ is Asia/Shanghai: 252ms test: localtime_r ... TZ is NULL and isdst=1: 161ms TZ is NULL and isdst=0: 160ms TZ is NULL and isdst=-1: 161ms TZ is NULL and isdst undefined: 161ms TZ is empty and isdst=1: 160ms TZ is empty and isdst=0: 161ms TZ is empty and isdst=-1: 161ms TZ is empty and isdst undefined: 161ms TZ is Asia/Shanghai and isdst=1: 161ms TZ is Asia/Shanghai and isdst=0: 161ms TZ is Asia/Shanghai and isdst=-1: 161ms TZ is Asia/Shanghai and isdst undefined: 161ms test: mktime ... TZ is NULL and isdst=1: 199375ms TZ is NULL and isdst=0: 1488ms TZ is NULL and isdst=-1: 1483ms TZ is NULL and isdst undefined: 1497ms TZ is empty and isdst=1: 161057ms TZ is empty and isdst=0: 325ms TZ is empty and isdst=-1: 328ms TZ is empty and isdst undefined: 326ms TZ is Asia/Shanghai and isdst=1: 161558ms TZ is Asia/Shanghai and isdst=0: 321ms TZ is Asia/Shanghai and isdst=-1: 335ms TZ is Asia/Shanghai and isdst undefined: 328ms */ // localtime_r相关源代码: /* // The C Standard says that localtime and gmtime return the same pointer. struct tm _tmbuf; // 全局变量 struct tm * __localtime_r (t, tp) const time_t *t; struct tm *tp; { return __tz_convert (t, 1, tp); } // 非线程安全版本,用到了全局变量_tmbuf struct tm * localtime(t) const time_t *t; { return __tz_convert (t, 1, &_tmbuf); } struct tm * __tz_convert (const time_t *timer, int use_localtime, struct tm *tp) { 。。。 // 信号处理函数中调用非信号安全函数,可能造成死锁的地方 __libc_lock_lock (tzset_lock); // localtime_r未用到_tmbuf,只是localtime使用它!!! // 因此对于localtime_r,传递给tzset_internal的第一个参数总是为0(tp != &_tmpbuf), // 而对于localtime,它传递给tzset_internal的第一个参数总是为1 tzset_internal (tp == &_tmbuf && use_localtime, 1); 。。。 } // 决定性能的函数,原因是可能涉及文件操作, // 因此要想提升性能,则应当想办法避免操作文件!!! static void internal_function tzset_internal (always, explicit) int always; int explicit; { static int is_initialized; // 静态变量 const char *tz; // 对于mktime,参数always值总是为1 // 对于localtime,参数always值总是为1 // 对于localtime_r,参数always值总是为0 if (is_initialized && !always) return; // 对于localtime_r第一次调用后,后续都在这里直接返回! is_initialized = 1; tz = getenv ("TZ"); if (tz == NULL && !explicit) tz = TZDEFAULT; if (tz && *tz == '\0') tz = "Universal"; if (tz && *tz == ':') ++tz; // 如果不设置环境变量TZ,则下面这个if语句总是不成立!!! // 因此只有设置了环境变量TZ,才有可能在这里直接返回而不进入读文件操作__tzfile_read if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0) return; // 在这里返回则可以避免走到文件操作__tzfile_read if (tz == NULL) tz = TZDEFAULT; tz_rules[0].name = NULL; tz_rules[1].name = NULL; // Save the value of `tz'. free (old_tz); old_tz = tz ? __strdup (tz) : NULL; // 读文件,性能慢的原因 __tzfile_read (tz, 0, NULL); // Try to read a data file. if (__use_tzfile) return; 。。。 } */ // mktime相关源代码: /* time_t mktime (struct tm *tp) { #ifdef _LIBC // POSIX.1 8.1.1 requires that whenever mktime() is called, the // time zone names contained in the external variable 'tzname' shall // be set as if the tzset() function had been called. __tzset (); #endif // __mktime_internal会调用localtime_r, // isdst的取值在这里会严重影响到mktime的性能 return __mktime_internal (tp, __localtime_r, &localtime_offset); } void __tzset (void) { __libc_lock_lock (tzset_lock); // 和localtime_r一样也会调用tzset_internal tzset_internal (1, 1); if (!__use_tzfile) { // Set `tzname'. __tzname[0] = (char *) tz_rules[0].name; __tzname[1] = (char *) tz_rules[1].name; } __libc_lock_unlock (tzset_lock); } */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/time.h> #include <time.h> static void test_localtime(int M); // 测试localtime性能 static void test_localtime_r(int M); // 测试localtime_r性能 static void test_mktime(int M); // 测试mktime性能 int main(int argc, char* argv[]) { const int M = (argc<2)? 1000000: atoi(argv[1]); test_localtime(M); printf("\n"); test_localtime_r(M); printf("\n"); test_mktime(M); return 0; } // test_localtime void test_localtime(int M) { int i; time_t now = time(NULL); struct timeval tv1, tv2; printf("test: localtime ...\n"); unsetenv("TZ"); // test1 { struct tm* result1; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { result1 = localtime(&now); } gettimeofday(&tv2, NULL); printf("TZ is NULL: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "", 0); // test2 { struct tm* result2; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { result2 = localtime(&now); } gettimeofday(&tv2, NULL); printf("TZ is empty: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "Asia/Shanghai", 0); // test3 { struct tm* result3; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { result3 = localtime(&now); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } } // test_localtime_r void test_localtime_r(int M) { int i; time_t now = time(NULL); struct timeval tv1, tv2; printf("test: localtime_r ...\n"); unsetenv("TZ"); // test1 { struct tm result1; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result1_; memcpy(&result1_, &result1, sizeof(result1_)); result1_.tm_isdst = 1; localtime_r(&now, &result1_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test2 { struct tm result2; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result2_; memcpy(&result2_, &result2, sizeof(result2_)); result2_.tm_isdst = 0; localtime_r(&now, &result2_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test3 { struct tm result3; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result3_; memcpy(&result3_, &result3, sizeof(result3_)); result3_.tm_isdst = -1; localtime_r(&now, &result3_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test4 { struct tm result4; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result4_; memcpy(&result4_, &result4, sizeof(result4_)); localtime_r(&now, &result4_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "", 0); // test5 { struct tm result5; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result5_; memcpy(&result5_, &result5, sizeof(result5_)); result5_.tm_isdst = 1; localtime_r(&now, &result5_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test6 { struct tm result6; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result6_; memcpy(&result6_, &result6, sizeof(result6_)); result6_.tm_isdst = 0; localtime_r(&now, &result6_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test7 { struct tm result7; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result7_; memcpy(&result7_, &result7, sizeof(result7_)); result7_.tm_isdst = -1; localtime_r(&now, &result7_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test8 { struct tm result8; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result8_; memcpy(&result8_, &result8, sizeof(result8_)); result8_.tm_isdst = -1; localtime_r(&now, &result8_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "Asia/Shanghai", 0); // test9 { struct tm result9; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result9_; memcpy(&result9_, &result9, sizeof(result9_)); result9_.tm_isdst = 1; localtime_r(&now, &result9_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test10 { struct tm result10; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result10_; memcpy(&result10_, &result10, sizeof(result10_)); result10_.tm_isdst = 0; localtime_r(&now, &result10_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test11 { struct tm result11; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result11_; memcpy(&result11_, &result11, sizeof(result11_)); result11_.tm_isdst = -1; localtime_r(&now, &result11_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test12 { struct tm result12; gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result12_; memcpy(&result12_, &result12, sizeof(result12_)); localtime_r(&now, &result12_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } } // test_mktime void test_mktime(int M) { int i; time_t now = time(NULL); struct timeval tv1, tv2; printf("test: mktime ...\n"); unsetenv("TZ"); // test1 { struct tm result1; localtime_r(&now, &result1); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result1_; memcpy(&result1_, &result1, sizeof(result1_)); result1_.tm_isdst = 1; mktime(&result1_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test2 { struct tm result2; localtime_r(&now, &result2); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result2_; memcpy(&result2_, &result2, sizeof(result2_)); result2_.tm_isdst = 0; mktime(&result2_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test3 { struct tm result3; localtime_r(&now, &result3); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result3_; memcpy(&result3_, &result3, sizeof(result3_)); result3_.tm_isdst = -1; mktime(&result3_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test4 { struct tm result4; localtime_r(&now, &result4); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result4_; memcpy(&result4_, &result4, sizeof(result4_)); mktime(&result4_); } gettimeofday(&tv2, NULL); printf("TZ is NULL and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "", 0); // test5 { struct tm result5; localtime_r(&now, &result5); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result5_; memcpy(&result5_, &result5, sizeof(result5_)); result5_.tm_isdst = 1; mktime(&result5_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test6 { struct tm result6; localtime_r(&now, &result6); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result6_; memcpy(&result6_, &result6, sizeof(result6_)); result6_.tm_isdst = 0; mktime(&result6_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test7 { struct tm result7; localtime_r(&now, &result7); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result7_; memcpy(&result7_, &result7, sizeof(result7_)); result7_.tm_isdst = -1; mktime(&result7_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test8 { struct tm result8; localtime_r(&now, &result8); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result8_; memcpy(&result8_, &result8, sizeof(result8_)); mktime(&result8_); } gettimeofday(&tv2, NULL); printf("TZ is empty and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } setenv("TZ", "Asia/Shanghai", 0); // test9 { struct tm result9; localtime_r(&now, &result9); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result9_; memcpy(&result9_, &result9, sizeof(result9_)); result9_.tm_isdst = 1; mktime(&result9_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test10 { struct tm result10; localtime_r(&now, &result10); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result10_; memcpy(&result10_, &result10, sizeof(result10_)); result10_.tm_isdst = 0; mktime(&result10_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=0: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test11 { struct tm result11; localtime_r(&now, &result11); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result11_; memcpy(&result11_, &result11, sizeof(result11_)); result11_.tm_isdst = -1; mktime(&result11_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst=-1: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } // test12 { struct tm result12; localtime_r(&now, &result12); gettimeofday(&tv1, NULL); for (i=0; i<M; ++i) { struct tm result12_; memcpy(&result12_, &result12, sizeof(result12_)); mktime(&result12_); } gettimeofday(&tv2, NULL); printf("TZ is Asia/Shanghai and isdst undefined: %ums\n", (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000); } }
相关文章推荐
- Loadrunner调用Webservice接口进行性能测试时的方法及优化总结
- 第121课: Spark Streaming性能优化:通过摄像头图像处理案例来说明Spark流处理性能评估新方法及性能调优参数测试
- Java性能优化指南系列(一):概述和性能测试方法
- Java性能优化指南系列(一):概述和性能测试方法
- Java性能优化指南系列(一):概述和性能测试方法
- 从某次测试过程中,得到的MySQL性能优化的建议,和定位问题的方法 推荐
- 性能测试:前端性能优化方法
- H5前端性能测试点及优化方法
- Apache Web Server性能测试中大量TIME_WAIT解决方法 及 Linux sysctl.conf 优化解决方案
- JavaScript字符串数组拼接的性能测试及优化方法
- Loadrunner 调用 Webservice 接口 进行 性能测试 时的方法及优化总结
- ASP.NET中常用的优化性能的方法(转贴,Icyer收集整理)
- Web下的性能测试与优化
- 性能测试方法——推荐阅读
- 性能测试方法——推荐阅读
- ASP.NET中常用的优化性能的方法(转贴,Icyer收集整理)
- 性能测试方法全面综述
- ASP.NET中常用的优化性能的方法
- 性能测试方法
- ASP.NET中常用的优化性能方法