- 1、优化策略
- 2、简单测试
- 3、继续优化
- 4、嵌入log
本次将对日志进行一次优化,参考一篇Ring-Log日志库,基于双向、循环的链表的数据结构实现高效率、易拓展的日志库;
========》每秒百万级高效C++异步日志实践《========
1、优化策略为了减少对localtime的调用,使用以下策略 RingLog使用变量_sys_acc_sec记录写上一条日志时,系统经过的秒数(从1970年起算)、使用变量_sys_acc_min记录写上一条 日志时,系统经过的分钟数,并缓存写上一条日志时的年月日时分秒year、mon、day、hour、min、sec,并缓存UTC日志格式字符 串; 每当准备写一条日志: - 调用gettimeofday获取系统经过的秒tv.tv_sec,与_sys_acc_sec比较; - 如果tv.tv_sec 与 _sys_acc_sec相等,说明此日志与上一条日志在同一秒内产生,故年月日时分秒是一样的,直接使用 缓存即可; - 否则,说明此日志与上一条日志不在同一秒内产生,继续检查:tv.tv_sec/60即系统经过的分钟数与_sys_acc_min比较; - 如果tv.tv_sec/60与_sys_acc_min相等,说明此日志与上一条日志在同一分钟内产生,故年月日时分是一样的,年月日时 分 使用缓存即可,而秒sec = tv.tv_sec%60,更新缓存的秒sec,重组UTC日志格式字符串的秒部分; - 否则,说明此日志与上一条日志不在同一分钟内产生,调用localtime重新获取UTC时间,并更新缓存的年月日时分秒,重组 UTC日志格式字符串2、简单测试
#include3、继续优化#include #include using namespace std; struct UtcTimer { UtcTimer() { struct timeval tv; gettimeofday(&tv, NULL); _sys_acc_sec = tv.tv_sec; // 秒 _sys_acc_min = _sys_acc_sec / 60; // 分 struct tm tm; localtime_r((time_t*)&_sys_acc_sec, &tm); year = tm.tm_year + 1900; mon = tm.tm_mon + 1; day = tm.tm_mday; hour = tm.tm_hour; min = tm.tm_min; sec = tm.tm_sec; reset_utc_fmt(); } uint64_t get_curr_time(int* p_msec = NULL) { struct timeval tv; gettimeofday(&tv, NULL); if (p_msec) *p_msec = tv.tv_usec / 1000; if ((uint32_t)tv.tv_sec != _sys_acc_sec) { sec = tv.tv_sec % 60; _sys_acc_sec = tv.tv_sec; if (_sys_acc_sec / 60 != _sys_acc_min) { _sys_acc_min = _sys_acc_sec / 60; struct tm cur_tm; localtime_r((time_t*)&_sys_acc_sec, &cur_tm); year = cur_tm.tm_year + 1900; mon = cur_tm.tm_mon + 1; day = cur_tm.tm_mday; hour = cur_tm.tm_hour; min = cur_tm.tm_min; reset_utc_fmt(); } else { reset_utc_fmt_sec(); } } return tv.tv_sec; } int year, mon, day, hour, min, sec; char utc_fmt[20]; private: void reset_utc_fmt() { snprintf(utc_fmt, 20, "%d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void reset_utc_fmt_sec() { snprintf(utc_fmt + 17, 3, "%02d", sec); } uint64_t _sys_acc_min; uint64_t _sys_acc_sec; }; void func1() { UtcTimer ut; for(int i=0; i<1000000000; ++i) ut.get_curr_time(); } void func2() { time_t _sys_acc_sec; struct tm tm; for(int i=0; i<1000000000; ++i) localtime_r((time_t*)&_sys_acc_sec, &tm); } int main(int argc, char* argv[]) { clock_t begin = clock(); func1(); clock_t end = clock(); cout << "tick=" << double(end - begin)/1000 << endl; return 0; }
将结构体中的成员去除,用struct tm取代; 若秒数改变只需将tm的tm_sec修改即可;
#include4、嵌入log#include #include #include using namespace std; struct UtcTimer { UtcTimer() { struct timeval tv; gettimeofday(&tv, NULL); _sys_acc_sec = tv.tv_sec; // 秒 _sys_acc_min = _sys_acc_sec / 60; // 分 struct tm tm; localtime_r((time_t*)&_sys_acc_sec, &tm); year = tm.tm_year + 1900; mon = tm.tm_mon + 1; day = tm.tm_mday; hour = tm.tm_hour; min = tm.tm_min; sec = tm.tm_sec; reset_utc_fmt(); } uint64_t get_curr_time(int* p_msec = NULL) { struct timeval tv; gettimeofday(&tv, NULL); if (p_msec) *p_msec = tv.tv_usec / 1000; if ((uint32_t)tv.tv_sec != _sys_acc_sec) { sec = tv.tv_sec % 60; _sys_acc_sec = tv.tv_sec; if (_sys_acc_sec / 60 != _sys_acc_min) { _sys_acc_min = _sys_acc_sec / 60; struct tm cur_tm; localtime_r((time_t*)&_sys_acc_sec, &cur_tm); year = cur_tm.tm_year + 1900; mon = cur_tm.tm_mon + 1; day = cur_tm.tm_mday; hour = cur_tm.tm_hour; min = cur_tm.tm_min; reset_utc_fmt(); } else { reset_utc_fmt_sec(); } } return tv.tv_sec; } int year, mon, day, hour, min, sec; char utc_fmt[20]; private: void reset_utc_fmt() { snprintf(utc_fmt, 20, "%d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec); } void reset_utc_fmt_sec() { snprintf(utc_fmt + 17, 3, "%02d", sec); } uint64_t _sys_acc_min; uint64_t _sys_acc_sec; }; struct testTimer { testTimer() { time_t t = time(0); localtime_r(&t, &tm); } void listen() { time_t t = time(0); if(tm.tm_sec != t % 60) { if(tm.tm_min == t / 60 % 60) { tm.tm_sec = t % 60; }else { localtime_r(&t, &tm); } } } void p() { std::cout << tm.tm_sec << ":" << tm.tm_min << std::endl; } struct tm tm; }; void func1() { UtcTimer ut; for(int i=0; i<100000000; ++i) { ut.get_curr_time(); } } void func5() { testTimer ut; for(int i=0; i<100000000; ++i) { ut.listen(); } } int main(int argc, char* argv[]) { clock_t begin = clock(); func1(); clock_t end = clock(); cout << "tick=" << double(end - begin)/CLOCKS_PER_SEC << "秒" << endl; begin = clock(); func5(); end = clock(); cout << "tick=" << double(end - begin)/CLOCKS_PER_SEC << "秒"<< endl; return 0; }



