栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
    • 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、简单测试


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


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修改即可;

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

4、嵌入log


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026721.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号