Skip to content

性能测量方法与指标

查看 Markdown

使用独立的 Release C++ 程序在本地测量。CI 只执行回归与 smoke 检查;公开报告记录机器、配置、原始数据和测量范围。

单项基准

build/benchmarks/arknet_loopback_benchmark \
  --protocol tcp --payload 1024 --clients 16 --window 16 \
  --io-model shared --io-threads 1 --work 0 --warmup 0.25 --seconds 1
build/benchmarks/arknet_coroutine_benchmark \
  --execution coroutine --protocol tcp --payload 1024 --clients 16 --window 16 \
  --io-model shared --io-threads 4 --work 0 --warmup 0.25 --seconds 1

每个程序向标准输出写入一条 JSON 结果,失败时返回非零退出码。 用简短 shell 循环为同一配置启动独立进程重复测量:

for repetition in 1 2 3; do
  build/benchmarks/arknet_loopback_benchmark \
    --protocol tcp --payload 1024 --clients 16 --window 16 \
    --io-model shared --io-threads 1 --work 0 --warmup 0.25 --seconds 1 \
    > "build/tcp-${repetition}.json" || exit 1
done

性能矩阵

原有 IO 拓扑基线与扩展负载矩阵是独立数据集。 包体、批量与执行方式对比固定连接数,分别比较其他维度。

包体、批量与执行方式

维护者可用 bash scripts/benchmark_matrix.sh 收集完整矩阵。 只有批量工具需要 jq、GNU timeout(macOS 可用 gtimeout)、shasum 和常用 shell 工具。它直接启动相同的 C++ 程序,保留执行命令、JSON、失败信息、机器信息和哈希。

bash scripts/benchmark_matrix.sh --executable build/benchmarks/arknet_loopback_benchmark \
  --backend standalone --certs tests/certs --clients 16 --windows 1 4 16 64 \
  --payloads 64 1024 16384 --io-models shared sharded --io-threads 1 4 \
  --seconds 1 --warmup 0.25 --repetitions 3 --keep-going \
  --output benchmarks/results/local-dimensions-standalone-callback.json
bash scripts/benchmark_matrix.sh --executable build/benchmarks/arknet_coroutine_benchmark \
  --backend standalone --certs tests/certs --protocols tcp --clients 16 \
  --windows 1 4 16 64 --payloads 64 1024 16384 \
  --io-models shared sharded --io-threads 1 4 --work-values 0 10000 \
  --execution-modes callback coroutine --seconds 1 --warmup 0.25 --repetitions 3 \
  --output benchmarks/results/local-dimensions-standalone-native.json

再用 Boost 构建目录中的两个可执行文件运行相同命令,将 --backend 改为 boost, 输出分别设为 local-dimensions-boost-callback.json 和 local-dimensions-boost-native.json。 每种依赖方案包含 756 次 arknet 回调测量和 432 次原生 TCP 对照测量。七种协议均使用显式设置的四档在途请求上限, 包括 UDP;批量大小与连接数分别设置。

原生测试使用相同的服务端整批读取与回显、客户端整批读写、包体检查、CPU 计算和 每连接 strand,对比 Asio 回调与 C++20 协程。它测量整批完成 RTT;每批只有 一个请求时等同于逐消息 RTT。arknet 的公共协程端点 API 仍为 TODO。 两种执行方式的 CPU 时间均包含预热与测量;服务端在回显前对批次中的每条消息 分别执行指定计算。

--keep-going 保留失败负载配置,完成请求的矩阵;只要有失败就返回非零退出码。 失败组展示错误和 UDP 丢包量,不参与有效吞吐量、RTT 对比。每组用独立进程 重复测量三次;原生测试在重复轮次之间交替执行顺序。流量采用闭环请求,RTT 包含排队时间,不测量独立定时到达的请求负载。 测量完成后,可按指标与图表创建离线报告生成环境,再使用四个数据文件生成对比:

build/report-venv/bin/python benchmarks/dimensions.py \
  --reports benchmarks/results/local-dimensions-standalone-callback.json \
            benchmarks/results/local-dimensions-boost-callback.json \
            benchmarks/results/local-dimensions-standalone-native.json \
            benchmarks/results/local-dimensions-boost-native.json \
  --output-dir docs/performance

原有 IO 拓扑基线

bash scripts/benchmark_matrix.sh --executable build/benchmarks/arknet_loopback_benchmark \
  --certs tests/certs --seconds 1 --warmup 0.25 --repetitions 3 \
  --output benchmarks/results/local-loopback.json
bash scripts/benchmark_matrix.sh --executable build/benchmarks/arknet_coroutine_benchmark \
  --certs tests/certs --protocols tcp --work-values 0 10000 \
  --seconds 1 --warmup 0.25 --repetitions 3 \
  --output benchmarks/results/local-coroutine.json

每种依赖方案的回调矩阵包含 630 次测量: 七种协议 × 三种消息大小 × 两档流量 × 五种拓扑 × 三次重复。 协程 TCP 矩阵包含 180 次测量,增加两档业务计算量。 运行脚本默认测量三秒、预热一秒;上面的命令与较短的本机基线一致。 关闭 TLS 时应指定 --protocols tcp udp websocket http。 这些命令在当前代码上复现基线负载参数。发布的基线记录了原始源码和程序哈希; 复现当时的实现应使用对应归档源码。

维度 参数
协议 使用 use_dgram 的 TCP、UDP、WebSocket、TCPS、WSS、HTTP、HTTPS
消息大小 64、1024、16384 字节
流量 1 个客户端/window 1;16 个客户端/window 16(UDP 为1)
IO 一个 context,分别由 1、2、4 个线程运行;2 或 4 个 context,各由一个线程运行
协程业务计算 服务端每次回显前执行0或10000次确定性 CPU 计算

一个 io_context 可以由一个或多个线程运行。多线程配置为每个连接使用独立 strand;分片配置为每个 io_context 使用一个运行线程。客户端和服务端共享 同一套 IO 调度资源。只有一个 context 时,两种配置相同,因此不重复测量。 IO 模型与协程说明业务选型。

每次测量启动独立进程,先预热,再测量,最后最多等待两秒收完未完成流量。 收集数据前停止并行构建和其他高负载任务。运行脚本保留失败前的部分结果; 数据/顺序错误、发送拒绝/完成错误、UDP 丢失、异常断连和未完成流量均使测量无效。

指标与图表

指标 定义
往返/s 完成回显数除以测量墙钟时间
Payload MiB/s 2 × payload字节数 × 完成往返数 / 秒 / 1048576,不含头部和加密
RTT p50/p95/p99 从提交发送至匹配回显,包含排队和业务处理;使用采样
平均 CPU 占用率 进程 CPU 时间除以同一区间的墙钟时间,再乘 100%;单核 100%,多线程可超过 100%
Peak RSS 整个进程的常驻内存峰值,不证明没有泄漏
错误 数据/顺序、发送完成/拒绝、丢失/未完成、异常与收尾超时

CPU 包含同一进程中客户端、服务端的全部线程,不代表功耗。本机有 14 个逻辑核心, 进程 400% 相当于整机计算容量的约 28.6%。新程序记录 cpu_elapsed_seconds; 历史结果未记录独立的 CPU 采样墙钟区间,报告标为估算:协议测试用测量与排空时长, 原生回调/协程对照用预热加测量时长作分母。

两个基准程序及批量脚本支持 --address-family ipv6,通过 ::1 测试; 默认 ipv4 使用 127.0.0.1。现有性能报告测量 IPv4,IPv6 的用法与验证范围见 IPv4 与 IPv6。

UDP 请求 64 KiB 发送缓冲和 4 MiB 接收缓冲,JSON 记录服务端实际值和客户端最小/最大值。 操作系统可能限制请求。默认 UDP 窗口不模拟不可靠网络。 本机回环接口 lo0 的 MTU 为 16384 字节。

Python 和 Matplotlib 是可选的离线报告工具,不参与 C++ 网络测试的编译、启动或测量。 测量结束后,可将同机器、同源码哈希和相同测量时长的完整数据转成图表与中英文表格:

python3 -m venv build/report-venv
build/report-venv/bin/pip install -r benchmarks/requirements-report.txt
build/report-venv/bin/python benchmarks/report.py \
  --reports benchmarks/results/local-loopback.json benchmarks/results/local-coroutine.json \
  --output-dir docs/performance \
  --host-description "Actual hardware, compiler, dependencies and Release build flags"

Windows 使用 build/report-venv/Scripts/python.exe。 Matplotlib 只用于报告生成。生成器拒绝未完成、失败、重复或配置不兼容的数据。 图表显示重复测量的中位数和最小/最大值,误差线不是置信区间。 延迟是各次运行采样分位数的中位数,不是合并样本后的分位数。

报告工具维护者可以单独运行可选的 Python 检查:

build/report-venv/bin/python -m unittest discover -s benchmarks -p 'test_report.py' -v
build/report-venv/bin/python -m unittest discover -s benchmarks -p 'test_dimensions.py' -v

每连接允许多条在途请求时,协程测试程序测量整批 RTT,回调测试程序持续 补充请求并测量逐消息 RTT。只在同一测试程序内比较 IO 配置,不能据此 从这组原有基线推导协程相对回调的加速比。上面的原生对照测试为两种执行方式 使用相同测量方法。

Navigation

Type to search…

↑↓ navigate↵ selectEsc close