1.日志库的挑战
日志是调试和监控系统的重要手段。高性能场景下,日志不能成为性能瓶颈,尤其不能因为磁盘I/O或锁竞争拖慢业务线程。C++社区中spdlog是目前最流行的高性能日志库,完全由头文件和C++11实现,采用异步日志、格式化缓存、无锁队列等优化。
参考:https://amwtm.cn/category/entrance.html
2.spdlog的核心设计
异步日志器:业务线程只将日志消息放入无锁队列(moodycamel::ConcurrentQueue),后台线程负责写磁盘或控制台。这使业务线程的耗时仅几十纳秒。
格式化优化:使用fmtlib(C++20std::format前身)进行快速格式化。自定义formatter避免stringstream开销。
Logger层级:支持多logger(如error_logger、access_logger),各自独立控制级别和输出目标。
轮转文件:内置按大小或时间轮转,自动压缩。
3.使用实例
创建一个异步文件日志器:
autofile_logger=spdlog::basic_logger_mt("file_logger","logs/app.log");
file_logger->set_level(spdlog::level::info);
file_logger->info("User{}loggedin",user_id);
宏定义可控制调试模式下打印更多信息。
4.性能对比
在基准测试中,spdlog异步日志每秒可处理200万条简单日志(平均每条<0.5微秒),而同步日志的fprintf可能高达数十微秒。内存占用方面,队列缓冲区可配置大小,避免无限增长。
参考:https://amwtm.cn/category/balcony.html
5.案例:交易系统的审计日志
某高频交易系统必须记录每个订单的完整生命周期(接收、转发、成交),且要求极低的性能损耗。使用spdlog异步日志:
业务线程调用order_logger->info(...)后立即返回。
单独的后台线程(优先级较低)批量写入SSD,每秒可记录30万条审计日志。
日志格式包含微秒时间戳(%E说明符),用于事后回放。
日志轮转按每小时分文件,超过1GB自动压缩,节省磁盘。
6.配置建议
级别过滤:发布版本使用warn级别,减少日志量。
同步日志:对于关键告警,可临时设为同步模式,确保即使后台线程崩溃也能输出。
自定义sink:可输出到syslog、网络、Elasticsearch(通过HTTP)。
7.与其他库对比
glog(Google):功能丰富,但性能稍逊。
log4cxx:Apache移植,较重,依赖多。
spdlog:轻量、快速、现代C++,成为首选。
8.总结
C++高性能日志库spdlog展示了如何通过异步和零拷贝设计,使日志记录几乎不影响业务性能。对于任何对延迟敏感的C++应用(游戏、交易、实时系统),spdlog是理想的日志基础设施。
参考:https://amwtm.cn