性能基准测试结果
所有基准测试均在运行 bleRPC 固件并启用端到端加密(AES-128-GCM)的 nRF54L15 DK peripheral 上进行。MTU 协商为 247 字节。连接间隔因平台而异。
吞吐量对比
Python (macOS)
30.3
KB/s flash read
CI: 15ms
iOS (iPhone 16)
32.1
KB/s flash read
CI: 30ms
Android (Pixel 5)
59.0
KB/s flash read
CI: 30ms
各平台详细结果
Python Central (macOS, bleak)
连接间隔:15ms(macOS 协商)— 测试代码
| 基准测试 | 结果 | 详细信息 |
|---|---|---|
| flash_read_throughput | 30.3 KB/s | 10 次 8192 字节,264.2 ms/次 |
| flash_read_overhead | 60.1 ms/次 | 1 字节 x 20 次 |
| echo_roundtrip | 60.6 ms/次 | 50 次 |
| data_write_throughput | 3.3 KB/s | 200 字节 x 20 次,59.9 ms/次 |
| counter_stream (P→C) | 5.8 ms/条 | 20 条,共 117 ms |
| counter_upload (C→P) | 7.4 ms/条 | 20 条,共 147 ms |
| 功能测试 | 结果 | 详细信息 |
|---|---|---|
| echo_basic | 通过 | |
| echo_empty | 通过 | |
| echo_max_length | 通过 | 256 字符字符串 |
| flash_read_basic | 通过 | 16 字节 |
| flash_read_8kb | 通过 | 8192 字节 |
| data_write_basic | 通过 | 1024 字节 |
| data_write_8kb | 通过 | 8192 字节 |
| multi_container_echo | 通过 | 250 字符字符串 |
| counter_stream | 通过 | 5 条 |
| counter_stream_large | 通过 | 20 条 |
| counter_upload | 通过 | 5 条 |
| counter_upload_large | 通过 | 20 条 |
iOS Central (iPhone 16, CoreBluetooth)
连接间隔:30ms(iOS 协商)— 测试代码
| 基准测试 | 结果 | 详细信息 |
|---|---|---|
| flash_read_throughput | 32.1 KB/s | 10 次 8192 字节,249.0 ms/次 |
| flash_read_overhead | 62.3 ms/次 | 1 字节 x 20 次 |
| echo_roundtrip | 60.0 ms/次 | 50 次 |
| data_write_throughput | 3.3 KB/s | 200 字节 x 20 次,60.0 ms/次 |
| counter_stream (P→C) | 6.1 ms/条 | 20 条,共 121 ms |
| counter_upload (C→P) | 4.5 ms/条 | 20 条,共 91 ms |
| 功能测试 | 结果 | 详细信息 |
|---|---|---|
| echo_basic | 通过 | |
| echo_empty | 通过 | |
| flash_read_basic | 通过 | 64 字节 |
| flash_read_8kb | 通过 | 8192 字节 |
| data_write | 通过 | 64 字节 |
| counter_stream | 通过 | 5 条 |
| counter_upload | 通过 | 5 条 |
Android Central (Pixel 5)
连接间隔:30ms(Android 协商)— 测试代码
| 基准测试 | 结果 | 详细信息 |
|---|---|---|
| flash_read_throughput | 59.0 KB/s | 10 次 8192 字节,135.7 ms/次 |
| flash_read_overhead | 90.4 ms/次 | 1 字节 x 20 次 |
| echo_roundtrip | 62.2 ms/次 | 50 次 |
| data_write_throughput | 3.2 KB/s | 200 字节 x 20 次,60.3 ms/次 |
| counter_stream (P→C) | 3.7 ms/条 | 20 条,共 73 ms |
| counter_upload (C→P) | 5.1 ms/条 | 20 条,共 101 ms |
| 功能测试 | 结果 | 详细信息 |
|---|---|---|
| echo_basic | 通过 | |
| echo_empty | 通过 | |
| flash_read_basic | 通过 | 64 字节 |
| flash_read_8kb | 通过 | 8192 字节 |
| data_write | 通过 | 64 字节 |
| counter_stream | 通过 | 5 条 |
| counter_upload | 通过 | 5 条 |
性能说明
连接间隔的影响
连接间隔(CI)是影响往返延迟的主要因素。每次请求–响应循环至少需要 2 个连接事件:
- macOS (bleak):CI = 15ms → 约 30ms 往返
- iOS (iPhone 16):CI = 30ms → 约 60ms 往返
- Android (Pixel 5):CI = 30ms → 约 60ms 往返,但由于每个连接事件发送更多数据包,吞吐量最高
Peripheral 广播的首选 CI 为 15–30ms(PREF_MIN_INT=12, PREF_MAX_INT=24)。实际 CI 由 Central 的操作系统决定。
加密开销
端到端加密每次传输增加 20 字节(4 字节计数器 + 16 字节 AES-GCM 标签)。对于大载荷(8 KB),此开销可以忽略不计(<0.3%)。AES-128-GCM 加密/解密本身在现代移动设备上是硬件加速的,即使对于 8 KB 载荷也只需 <1ms
吞吐量优化
- nanopb FT_CALLBACK:将 flash 数据直接流式传入 protobuf 编码,节省 4KB 静态 RAM
- 零拷贝响应:Protobuf 响应直接在容器头偏移处编码
- 无包间延迟:容器背靠背发送
- 每次 flash read 最大 8KB:延迟和吞吐量之间的最佳平衡