【C++模块实现】| 【02】日志系统优化

发布于:2022-07-24 ⋅ 阅读:(412) ⋅ 点赞:(0)

本次将对日志进行一次优化,参考一篇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、简单测试

在这里插入图片描述

/*----------------------------------------------------------------------
	> File Name: testClock.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Sun 24 Jul 2022 02:02:36 PM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <time.h>
#include <sys/time.h>

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;
}

3、继续优化

将结构体中的成员去除,用struct tm取代;
若秒数改变只需将tm的tm_sec修改即可;
/*----------------------------------------------------------------------
	> File Name: testTm.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Sun 24 Jul 2022 10:28:22 PM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>

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;
}

在这里插入图片描述

4、嵌入log

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到