应使用 std::chrono::high_resolution_clock 测量单次循环 tps,通过执行 n 次待测操作计算总耗时再换算为每秒次数,避免在循环内反复调用 now(),并需控制环境干扰(如 cpu 温度、电源模式等)以确保结果稳定。

怎么用 std::chrono 精确测单次循环的 TPS
直接用 clock() 或 time() 测 TPS 误差极大,尤其在毫秒级操作里。必须用 std::chrono::high_resolution_clock,它底层对接系统高精度计时器(Windows 是 QueryPerformanceCounter,Linux 是 CLOCK_MONOTONIC)。
关键不是“跑一秒看多少次”,而是“跑 N 次看耗多久”,再换算成每秒次数——否则调度抖动、CPU 频率变化都会污染结果。
- 别在循环里反复调用
now():每次调用有开销,会拉低测得的 TPS - 把待测操作放在一个纯函数里,确保编译器不优化掉(加
volatile或用do_not_optimize) - 重复运行足够多次(比如 100 万次),让总耗时远大于时钟分辨率(通常纳秒级)
- 示例:测一个简单加法的 TPS
auto start = std::chrono::high_resolution_clock::now(); for (int i = 0; i (end - start).count(); double tps = 1e9 * 1000000.0 / ns; // 单位:ops/sec
为什么 std::chrono::steady_clock 比 system_clock 更适合压测
system_clock 可能因 NTP 校时跳变,导致测出负耗时或突兀的 TPS 峰值;而 steady_clock 保证单调递增,专为间隔测量设计。
- 所有性能压测场景都应优先选
std::chrono::steady_clock - 它和
high_resolution_clock在多数平台是同一类型(GCC/Clang 下通常 alias),但语义更明确 - 不要用
std::chrono::system_clock::now()做耗时计算,哪怕只是临时调试
多线程下测整体 TPS 容易漏掉什么
多个线程并发执行同一操作时,TPS 不是单线程结果 × 线程数,共享资源(如全局计数器、内存分配器、锁)会成为瓶颈。
- 避免所有线程往同一个
int累加:++counter引发缓存行争用(false sharing),实测可能比单线程还慢 - 每个线程用局部变量计数,最后再汇总
- 若操作涉及 I/O 或锁,必须把等待时间计入耗时——否则测的是“CPU 时间”而非真实吞吐
- 启动线程前调用
std::this_thread::sleep_for(100ms)让系统调度稳定,避免首几轮被上下文切换干扰
TPS 数值忽高忽低,怎么判断是不是真波动
单次测量结果不可信。现代 CPU 的频率调节(Intel SpeedStep / AMD Cool'n'Quiet)、后台进程抢占、TLB / cache 预热状态都会造成 ±15% 波动。
- 至少运行 5–10 轮,取中位数,而非平均值(平均值会被异常值拖偏)
- 关掉 CPU 频率缩放:
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor - 用
taskset -c 0绑定到单核,排除跨核迁移开销 - 如果 TPS 在连续几轮里标准差 > 5%,说明测试本身不稳定,先检查是否触发了 GC(如有托管内存)、日志刷盘、或内存页缺页
真正稳定的 TPS 测量,核心不在代码写得多漂亮,而在把环境干扰项一个个摁死。CPU 温度、电源模式、ASLR 开关、甚至主板 BIOS 中的 C-states 设置,都可能让结果漂移。没控好这些,数字再好看也没意义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











