muduo日志库原理以及源码分析

muduo日志库以高性能著称,采用日志批量写入和双缓冲区技术。异步机制通过锁和条件变量保证数据安全,多个线程将日志存入缓冲区,满或超时后由单独线程写入磁盘。在使用上,muduo提供便捷的日志写入方式。
摘要由CSDN通过智能技术生成

muduo日志库特点

  • 日志批量写入
  • 批量唤醒写线程
  • 写日志用notify+wait_timeout 方式触发日志的写入
  • 锁的粒度,双缓冲,双队列
  • buffer默认 4M 缓冲区, buffers 是 buffer 队列, push 、 pop 时使用 move 语义 减少内存拷贝

muduo的这些特点使得其作为高性能日志库被广泛使用。

muduo日志库异步机制

muduo为了保证日志的写入速度快,采用异步机制处理日志信息。多个线程将日志信息保存在数据buffer中,等buffer装满了再将buffer放入日志队列,通过锁和条件变量保证日志队列的数据安全,最后由日志落盘线程将日志队列中的数据写入磁盘中。

在这里插入图片描述

日志写入固定缓冲区程序

void AsyncLogging::append(const char* logline, int len)
{
   
  // if(cnt++ == 50000)abort();
  MutexLockGuard lock(mutex_);    // 多线程加锁
  if (currentBuffer_->avail() > len)    // 判断buffer还有没有空间写入这条日志
  {
   
    currentBuffer_->append(logline, len); // 直接写入
  }
  else
  {
   
    buffers_.push_back(std::move(currentBuffer_));    // buffers_是vector,把buffer入队列
    // printf("push_back append_cnt:%d, size:%d\n", ++append_cnt, buffers_.size());
    if (nextBuffer_)  // 用了双缓存
    {
   
      currentBuffer_ = std::move(nextBuffer_);    // 如果不为空则将buffer转移到currentBuffer_
    }
    else
    {
   
      // 重新分配buffer
      currentBuffer_.reset(new Buffer); // Rarely happens如果后端写入线程没有及时读取数据,那要再分配buffer
    }
    currentBuffer_->append(logline, len);   // buffer写满了
    cond_.notify(); // 唤醒写入线程
  }
}

日志写入磁盘程序

void AsyncLogging::threadFunc()
{
   
  assert(running_ == true);
  latch_.countDown();
  LogFile output(basename_, rollSize_, false);
  BufferPtr newBuffer1(new Buffer); // 是给currentBuffer_
  BufferPtr newBuffer2(new Buffer); // 是给nextBuffer_
  newBuffer1->bzero();
  newBuffer2->bzero();
  BufferVector buffersToWrite;    // 保存要写入的日志
  buffersToWrite.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值