C++ 日志系统实战第六步:性能测试

全是通俗易懂的讲解,如果你本节之前的知识都掌握清楚,那就速速来看我的项目笔记吧~

本文项目结束!


性能测试

下面对日志系统做一个性能测试,测试一下平均每秒能打印多少条日志消息到文件。

主要的测试方法是:每秒能打印日志数 = 打印日志条数 / 总的打印日志消耗时间

主要测试要素:同步 / 异步 & 单线程 / 多线程

  • 100w + 条指定长度的日志输出所耗时间
  • 每秒可以输出多少条日志
  • 每秒可以输出多少 MB 日志

测试环境:

  • CPU: AMD Ryzen 7 5800H with Radeon Graphics 3.20 GHz
  • RAM: 16G DDR4 3200
  • ROM: 512G-SSD
  • OS: ubuntu-22.04TLS 虚拟机(2CPU 核心 / 4G 内存)

bench.cc

cpp 复制代码
#include"../logs/mylog.h"

#include<chrono>
void bench(const std::string &logger_name,size_t thread_count,size_t msg_count,size_t msg_len)
{
    //1.获取日志器
    mylog::Logger::ptr logger=mylog::get_logger(logger_name);
    if(logger.get()==nullptr)
    {
        return;
    }
    std::cout<<"开始测试:"<<msg_count<<"条日志,总大小为:"<<msg_count*msg_len/1024<<"KB"<<std::endl;
    //2.组织指定长度的日志消息
    std::string msg(msg_len-1,'a');//少一个字符,以便于结尾有换行符
    //3.创建指定数量的线程
    std::vector<std::thread> threads;
    size_t msg_per_thread=msg_count/thread_count;
    std::vector<double> cost_arry(thread_count);
    for(size_t i=0;i<thread_count;i++)
    {
        threads.emplace_back([&,i](){
            //4.线程函数内部开始计时
            auto start_time=std::chrono::high_resolution_clock::now();
            //5.开始循环写日志
            for(size_t j=0;j<msg_per_thread;j++)
            {
                logger->fatal(msg);
            }
            //6.线程函数內部结束计时
            auto end_time=std::chrono::high_resolution_clock::now();
           std::chrono::duration<double> cost=end_time-start_time;
            cost_arry[i]=cost.count();
            std::cout<<"线程 "<<i<<": "<<"\t 输出日志数量:"<<msg_per_thread<<"\t 总耗时:"<<cost.count()<<"s"<<std::endl;
        });
    }
    for(int i=0;i<thread_count;i++)
    {
        threads[i].join();
    }
    //7.计算总耗时:在多线程中,每个线程都会消耗时间,但是线程是并发执行的,所以总耗时是最高的线程的耗时
    double max_cost=0;
    for(int i=0;i<thread_count;i++)
    {
        if(cost_arry[i]>max_cost)
        {
            max_cost=cost_arry[i];
        }
    }
    size_t msg_per_sec=msg_count/max_cost;
    size_t size_pre_sec=(msg_count+msg_len)/(max_cost*1024);
    std::cout<<"总耗时:"<<max_cost<<"s"<<std::endl;
    std::cout<<"日志输出速度:"<<msg_per_sec<<"条/秒"<<std::endl;
    std::cout<<"日志输出速度:"<<size_pre_sec<<"KB/秒"<<std::endl;
}
void sync_bench()
{
    std::shared_ptr<mylog::Logger_builder> builder(new mylog::Global_logger_builder());
    builder->buildLoggerName("Sync_logger");
    builder->buildLimitLevel(mylog::Level::Debug);
    builder->buildLoggerType(mylog::LoggerType::Loggertype_Sync); // 同步日志器
    builder->buildFormatBuilder("%m%n");
    builder->buildSinks<mylog::FileSink>("./logfile/sync.log");
    builder->build();
    bench("Sync_logger",1,1000000,100);
}
void async_bench()
{
    std::shared_ptr<mylog::Logger_builder> builder(new mylog::Global_logger_builder());
    builder->buildLoggerName("Async_logger");
    builder->buildLimitLevel(mylog::Level::Debug);
    builder->buildLoggerType(mylog::LoggerType::Loggertype_Async); // 异步日志器
    builder->buildFormatBuilder("%m%n");
    builder->buildSinks<mylog::FileSink>("./logfile/async.log");
    builder->build();
    bench("Async_logger",3,1000000,100);
}
int main()
{
    //sync_bench();
    async_bench();
    return 0;
}

单线程:

多线程:

text.cc(用于普通情况)

cpp 复制代码
#include "../logs/mylog.h"


void loggerTest(const std::string &logger_name) {
    INFO("------------example--------------------");
    mylog::Logger::ptr lp = mylog::LoggerManager::getInstance().getLogger(logger_name);
    lp->debug("%s", "logger->debug");
    lp->info("%s", "logger->info");
    lp->warn("%s", "logger->warn");
    lp->error("%s", "logger->error");
    lp->fatal("%s", "logger->fatal");
    // INFO("---------------------------------------");
    
    std::string log_msg = "hello -";
    size_t fsize = 0;
    size_t count = 0;
    while(count < 10000) {
        std::string msg = log_msg + std::to_string(count++);
        lp->error("%s", msg.c_str());
    }
}
void functional_test() {
}
int main(int argc, char *argv[])
{
    std::shared_ptr<mylog::Logger_builder> builder(new mylog::Global_logger_builder());
    builder->buildLoggerName("Async_logger");
    builder->buildLimitLevel(mylog::Level::Debug);
    builder->buildLoggerType(mylog::LoggerType::Loggertype_Async); // 异步日志器
    builder->buildFormatBuilder("[%d{%H:%M:%S}][%t][%p][%c][%f:%l] %m%n");
    builder->buildSinks<mylog::StdoutSink>();
    builder->buildSinks<mylog::FileSink>("./logfile/test_file.log");
    builder->buildSinks<mylog::RollSinkbySize>("./logfile/test_roll.log", 1024 * 1024*0.6);
    builder->build();
    loggerTest("Async_logger");
    return 0;
}

text.cc(用于根据时间分配文件的情况)

cpp 复制代码
//对时间分块
#include "../logs/mylog.h"

void loggerTest(const std::string &logger_name) {
    INFO("------------example--------------------");
    mylog::Logger::ptr lp = mylog::LoggerManager::getInstance().getLogger(logger_name);
    lp->debug("%s", "logger->debug");
    lp->info("%s", "logger->info");
    lp->warn("%s", "logger->warn");
    lp->error("%s", "logger->error");
    lp->fatal("%s", "logger->fatal");
    // INFO("---------------------------------------");
    
    std::string log_msg = "hello -";
    size_t fsize = 0;
    size_t count = 0;
    time_t start_time = mylog::util::Date::getTime();
    while(mylog::util::Date::getTime() - start_time < 5) {
        std::string msg = log_msg + std::to_string(count++);
        usleep(1000);
        lp->error("%s", msg.c_str());
    }
}
void functional_test() {
}
int main(int argc, char *argv[])
{
    std::shared_ptr<mylog::Logger_builder> builder(new mylog::Global_logger_builder());
    builder->buildLoggerName("Async_logger");
    builder->buildLimitLevel(mylog::Level::Debug);
    builder->buildLoggerType(mylog::LoggerType::Loggertype_Async); // 异步日志器
    builder->buildFormatBuilder("[%d{%H:%M:%S}][%t][%p][%c][%f:%l] %m%n");
    builder->buildSinks<mylog::StdoutSink>();
    builder->buildSinks<mylog::FileSink>("./logfile/test_file.log");
    builder->buildSinks<mylog::RollSinkbyTime>("./logfile/test_roll.log", mylog::TimeInterval::SECOND); // 按时间分块
    builder->build();
    loggerTest("Async_logger");
    return 0;
}

感谢你看到这里~日志系统的项目已经全部实现完成了!

未来共同进步,期待你的关注👉【A charmer】

相关推荐
水饺编程10 分钟前
Visual Studio 软件操作:添加附加依赖项
c语言·c++·windows·visual studio
-To be number.wan29 分钟前
C++ 进阶技巧:如何让 cout << 自定义对象 正常输出?
开发语言·c++
序属秋秋秋1 小时前
《Linux系统编程之进程控制》【进程创建 + 进程终止】
linux·c语言·c++·操作系统·进程·进程创建·进程终止
上天_去_做颗惺星 EVE_BLUE1 小时前
C++学习:学生成绩管理系统
c语言·开发语言·数据结构·c++·学习
John_ToDebug1 小时前
Chromium WebUI 定制实践:从 C++ 注入到 JS 安全展示全链路解析
javascript·c++·chrome
水饺编程2 小时前
开源项目介绍:VirtuaNES 模拟器
c语言·c++·windows·visual studio
十五年专注C++开发2 小时前
CMake进阶:find_package使用总结
开发语言·c++·cmake·跨平台编译
闻缺陷则喜何志丹2 小时前
【计算几何】平面凸包
c++·数学·扫描线·凸包·单调性·上凸包·下凸包
-To be number.wan2 小时前
C++ 运算符重载入门:让“+”也能为自定义类型服务!
开发语言·c++
汉克老师2 小时前
GESP2025年12月认证C++一级真题与解析(编程题1 (小杨的爱心快递))
c++·数据类型·选择结构·格式输出