一个高效的异步日志

本文探讨了如何通过异步日志提高日志记录效率,避免频繁的write系统调用导致的性能损耗。介绍了使用C++实现异步日志的具体步骤,包括buffer类、用于写入文件的类、时间戳类和异步日志类的实现,以及基本流程。提供了GitHub仓库链接以供参考。
摘要由CSDN通过智能技术生成

假如让你自己去写一个日志程序,我想最原始且简单的想法因该是,首先将要写入日志文件的内容转化为字符串,然后调用write系统调用将其写入文件。这种实现方法的确就是我们程序最原始的日志方法。这种做法无疑是十分低效的,那么如何让我们的日志能够高效起来呢?本篇博文就是要给大家分享一种高效的日志–异步日志

1.异步日志要实现什么?

前言中我有告诉打下那种最原始且简单的日志方法很低效,那么它低效在什么地方了呢?
主要有如下几点

1.其每条日志内容都会调用write,我们都知道write为系统调用,每一条就调一次它,势必系统开销会很大
2.当我们在关键的地方调用write会不会导致关键部分的代码不能即使的执行?

上述俩个导致我们原始日志低效的主要原因的解决方案分别为:
(1)既然每条日志调用一次write会导致系统开销变大,那么我们就设计一个buffer将日志内容保存在buffer中,待buffer满之后在一次性调用write将其写入即可
(2)由于write可能会阻塞在当前位置,导致紧随其后的关键代码可能不能马上执行,那么我们就单独开个线程专门来执行write调用不就可以了么
根据我们的解决方案,我们可以总结出异步日志的基本流程因该为:

前段线程(我们的程序)负责将日志写入buffer中,当buffer写满之后,将buffer转交给后端线程(我们的负责专门调用write来写日志的线程),也就是一个典型的多生产者单消费者模式

2.异步日志的代码实现

接下来为大家介绍一下我用C++实现的的异步日志代码

(1)buffer类的实现
#ifndef FIX_BUFFER_H_
#define FIX_BUFFER_H_

#include <vector>
#include <string>
#include <assert.h>
#include <fcntl.h>


namespace netlib
{
    class FixBuffer
    {
        public:
            FixBuffer()
                :buffer_(1024*1024*4)   //初始化大小为4M
            {
                readableIndex_ = 0;
                writeableIndex_ = 0;
            }
            ~FixBuffer()
            {

            }
            int readableSize(void)  //可读字节数
            {
                return writeableIndex_ - readableIndex_;    
            }

            int writeableSize(void) //可写字节数
            {
                return buffer_.size() - writeableIndex_;
            }

            void append(const char *data,int len) //添加数据到buffer中
            {
                std::copy(data,data + len,getWritePeek());
                moveWriteIndex(len);
            }

            char *getReadPeek(void) //获得读位置的指针
            {
                return begin() + readableIndex_;
            }

            char *getWritePeek(void)    //获得写位置的指针
            {
                return begin() + writeableIndex_;
            }


            void moveWriteIndex(int len)    //移动可写下标
            {
                writeableIndex_ = writeableIndex_ + len;
            }

            void resetBuffer(void)  //重置buffer
            {
                readableIndex_ = 0;
                writeableIndex_ = 0;
            }

        private:
            char *begin()
            {
                return &*buffer_.begin();
            }


            std::vector<char> buffer_;
            int readableIndex_;
            int writeableIndex_;

   };
}

#endif

buffer用std::vector来实现,主要提供的对外接口为获取buffer的读写位置指针,可读可写的大小,往buffer中添加数据等,buffer为固定大小4M

(2)用于将日志写如文件的类

logfile.h

#ifndef LOG_FILE_H_
#define LOG_FILE_H_
namespace netlib
{
   
    class LogFile
    {
   
        public:
            LogFile(int rollSize);
            ~LogFile();
            //往磁盘里添加消息
            void append(char *log,int len);
            //滚动文件
            void rollFile(
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值