目录
本文详细说明ros2 中性能测试工具irobot_benchmark的编译和使用
编译
首先要保证有可用的ros2库
- 拉代码:git clone https://gitee.com/gongfengzztx/ros2-performance.git (对应github:git clone https://github.com/irobot-ros/ros2-performance.git)
- 修改submoduble中的代码路径(仅针对在github上拉代码会超时的情况,使用gitee代替):
bash
[submodule "performance_test_factory/external/json"]
path = performance_test_factory/external/json
- url = https://github.com/nlohmann/json
+ url = https://gitee.com/gongfengzztx/json
[submodule "performance_test_factory/external/cxxopts"]
path = performance_test_factory/external/cxxopts
- url = https://github.com/jarro2783/cxxopts
+ url = https://gitee.com/gongfengzztx/cxxopts
- submodule初始化和更新
bash
cd ros2-performance
git submodule update --init --recursive
- 编译
bash
colcon build
运行
以下使用官方的json配置文件示例并说明benchmark的使用方法和输出内容的解释
运行:
bash
source ./install/setup.bash
cd ./install/irobot_benchmark/lib/irobot_benchmark
./irobot_benchmark topology/sierra_nevada.json
输出内容如下:
bash
Subscriptions stats:
node topic size[b] received[#] late[#] too_late[#] lost[#] mean[us] sd[us] min[us] max[us] freq[hz] throughput[Kb/s]
lyon amazon 36 501 0 0 0 373 166 27 1819 100 3.52098
hamburg danube 8 501 0 0 0 102 85 21 1780 100 0.782306
hamburg ganges 16 501 0 0 0 126 116 8 1701 100 1.56458
hamburg nile 16 501 0 0 0 280 133 9 1668 100 1.56493
hamburg tigris 16 501 0 0 0 264 114 39 1296 100 1.56498
osaka parana 12 501 0 0 0 247 125 20 1450 100 1.17382
mandalay danube 8 501 1 0 0 120 98 26 2049 100 0.782345
mandalay salween 48 50 0 0 0 325 101 79 585 10 0.468873
ponce danube 8 501 1 0 0 132 104 28 2136 100 0.782358
ponce missouri 10000 50 0 0 0 139 58 53 332 10 97.6594
ponce volga 8 10 0 0 0 192 145 81 424 2 0.0156253
barcelona mekong 100 10 0 0 0 308 102 73 460 2 0.195378
georgetown lena 50 50 0 0 0 116 33 68 251 10 0.488256
geneva congo 16 50 0 0 0 255 84 35 409 10 0.156243
geneva danube 8 501 1 0 0 143 109 32 2214 100 0.782368
geneva parana 12 501 0 0 0 288 147 27 1731 100 1.17387
arequipa arkansas 16 50 0 0 0 54 35 24 177 10 0.156255
bash
Publishers stats:
node topic size[b] received[#] late[#] too_late[#] lost[#] mean[us] sd[us] min[us] max[us] freq[hz] throughput[Kb/s]
montreal amazon 36 0 0 0 0 110 49 11 302 100 3.52005
montreal danube 8 0 0 0 0 38 17 10 218 100 0.782043
montreal ganges 16 0 0 0 0 18 12 2 136 100 1.56407
montreal nile 16 0 0 0 0 41 16 4 187 100 1.56452
lyon tigris 16 0 0 0 0 41 14 10 172 100 1.56468
hamburg parana 12 0 0 0 0 39 13 8 172 100 1.17355
osaka salween 48 0 0 0 0 47 19 16 170 10 0.468835
mandalay missouri 10000 0 0 0 0 51 22 25 165 10 97.6539
ponce congo 16 0 0 0 0 13 4 6 29 10 0.156243
ponce mekong 100 0 0 0 0 46 11 23 64 2 0.195368
barcelona lena 50 0 0 0 0 52 16 29 110 10 0.488259
georgetown volga 8 0 0 0 0 23 18 7 50 2 0.0156243
geneva arkansas 16 0 0 0 0 17 9 9 58 10 0.156254
bash
System total:
received[#] mean[us] late[#] late[%] too_late[#] too_late[%] lost[#] lost[%]
5280 206 3 0.05682 0 0 0 0
针对以上内容进行说明:
- 明确概念:irobot_benchmark 是针对 DDS 通信的基准测试工具,核心逻辑是:
- Publisher(发布者):向指定 Topic 发送固定大小、固定频率的测试数据;
- Subscriber(订阅者):订阅对应 Topic,记录接收数据的时延、丢包、吞吐量等指标;
测试的核心是订阅者能否稳定接收发布者的消息,因此 Subscriptions stats 是核心参考 ,Publishers stats 是辅助信息。
- Subscriptions stats(订阅者统计)字段详解
| 字段 | 含义 | 单位 / 说明 |
|---|---|---|
| node | sub端node名称(如 lyon、hamburg) | |
| topic | topic | |
| size[b] | 单条消息的大小 | 字节byte |
| received[#] | 成功接收的消息总数 | |
| late[#] | "迟到" 的消息数(到达时间超过预期,但仍在容忍范围内) | 迟到≠丢包,仅时延超标 |
| too_late[#] | 严重迟到" 的消息数(到达时间远超容忍范围,视为无效) | 这类消息通常会被sub端丢弃 |
| lost[#] | 丢失的消息数(pub发送但sub未收到) | 丢包是通信可靠性的核心指标 |
| mean[us] | 消息端到端时延的平均值 | 微秒(us),从pub发送到sub接收的平均耗时 |
| sd[us] | 时延的标准差 | 微秒(us),反映时延的sd[us] 的离散程度,也就是抖动(Jitter),波动程度(值越小,时延越稳定) |
| min[us]/max[us] | 时延的最小值 / 最大值 | 微秒(us),反映时延的极端情况(max 大说明存在偶发的高时延) |
| freq[hz] | 订阅者实际接收到的消息频率 | hz |
| throughput[Kb/s] | sub接收消息的吞吐量 | 计算公式:(size * received * freq) / 1024(Kb/s) |
- Publishers stats(发布者统计)字段详解
| 字段 | 含义 |
|---|---|
| received[#] | 发布者侧 "感知到的接收数"(非实际接收):irobot_benchmark 中发布者不接收消息,因此该值恒为 0; |
| mean/sd/min/max | pub发送消息的本地处理时延(而非端到端时延),发布者组装 + 发送消息的本地耗时 |
| freq[hz] | 发布者预设的发送频率(而非实际接收频率):比如 100hz 表示发布者每秒尝试发送 100 条消息; |
| throughput[Kb/s] | 发布者理论发送吞吐量(而非实际接收吞吐量):计算公式 size * freq / 1024,与订阅者实际吞吐量对比可看损耗; |
- System total(系统总计)字段详解
| 字段 | 含义 |
|---|---|
| received[#] | 所有订阅者接收的消息总数 |
| mean[us] | 所有消息端到端时延的平均值 |
| late[#]/late[%] | 迟到消息总数 / 占比 |
| too_late[#/%] | 严重迟到消息总数 / 占比 |
| lost[#]/lost[%] | 丢包总数 / 占比 |
- 资源占用输出如下:
bash
time[ms] cpu[%] arena[KB] in_use[KB] mmap[KB] rss[KB] vsz[KB]
0 0 0 0 0 0 0
500 4.3 17400 16630 900 104640 823584
1000 3.4 17532 16633 900 104640 823584
1500 3.1 17664 16636 900 104640 889120
2000 2.9 17664 16636 900 104640 889120
2500 2.8 17664 16636 900 104640 889120
3000 2.8 17664 16636 900 104640 889120
3500 2.7 17664 16636 900 104640 889120
4000 2.7 17664 16636 900 104640 889120
4500 2.7 17664 16636 900 104640 889120
5000 2.7 17664 16636 900 104640 889120
5500 2.5 17664 16565 900 104800 889120
从这个内容输出可以得到:
- 采样间隔: 500ms
- 总时长: 5500ms
- 采样次数: 5500/500 = 11次 + 初始时间0 = 12个数据点
- 计算平均值:应当 /11
注意:资源监控记录的是整个测试进程随时间变化的资源消耗,不是按topic统计的。
为什么CPU使用率持续下降,从4.3%逐渐下降到2.5%?
- 动态库加载和初始化等额外开销
- CPU缓存预热,代码优化路径等
- 消息流的稳定建立:初始阶段需要服务发现等,后期趋于稳定
- 操作系统调度优化等原因,所以以下曲线完全合理
▲
│
高峰 │ 初始化开销
│ ╭───╮
稳定 │ │ ╰───────╮
│ │ │
└───┴───────────┴───▶ 时间
启动 稳定运行
输出内容
| 字段 | 含义 |
|---|---|
| time[ms] | 从测试开始的时间戳 |
| cpu[%] | CPU使用率百分比 |
| arena[KB] | 内存分配竞技场大小 |
| in_use[KB] | 实际使用的内存 |
| mmap[KB] | mmap分配的内存 |
| rss[KB] | 常驻内存集 |
| vsz[KB] | 虚拟内存大小 |
配置文件格式
bash
{
"nodes": [
{
"node_name": "ponce",
"subscribers":[
{"topic_name":"missouri", "msg_type":"stamped_vector"},
{"topic_name":"danube", "msg_type":"stamped_int64"},
{"topic_name":"volga", "msg_type":"stamped_int64"}
],
"publishers": [
{"topic_name": "mekong", "msg_type": "stamped_vector", "msg_size": 100, "period_ms": 500, "msg_pass_by":"shared_ptr"},
{"topic_name": "congo", "msg_type": "stamped4_int32", "period_ms": 100, "msg_pass_by":"shared_ptr"}
]
},
# ...
]
}