Benchmark Results
All benchmarks were performed against a nRF54L15 DK peripheral running bleRPC firmware. MTU was negotiated to 247 bytes. Connection interval varies by platform.
Throughput Comparison
Python (macOS)
30.3
KB/s flash read
CI: 15ms
iOS (iPhone 16)
26.4
KB/s flash read
CI: 30ms
Android (Pixel 5)
56.7
KB/s flash read
CI: 30ms
Detailed Results by Platform
Python Central (macOS, bleak)
Connection interval: 15ms (macOS negotiation)
| Test | Result | Details |
|---|---|---|
| flash_read_throughput | 30.3 KB/s | 10x 8192 bytes, 273 ms/call |
| flash_read_overhead | 34.2 ms/call | 1 byte x 20 calls |
| echo_basic | PASS | |
| echo_empty | PASS | |
| echo_max_length | PASS | 256-char string |
| flash_read_basic | PASS | 64 bytes |
| flash_read_8kb | PASS | 8192 bytes |
| multi_container_echo | PASS | Multi-container request |
iOS Central (iPhone 16, CoreBluetooth)
Connection interval: 30ms (iOS negotiation)
| Test | Result | Details |
|---|---|---|
| flash_read_throughput | 26.4 KB/s | 10x 8192 bytes, 302.8 ms/call |
| flash_read_overhead | 59.9 ms/call | 1 byte x 20 calls |
| echo_roundtrip | 60.0 ms/call | 50 calls |
| data_write_throughput | 3.3 KB/s | 200 bytes x 20 calls, 60.0 ms/call |
| counter_stream (P→C) | 6.1 ms/item | 20 items in 123ms |
| counter_upload (C→P) | 5.9 ms/item | 20 items in 118ms |
| echo_basic | PASS | |
| echo_empty | PASS | |
| flash_read_basic | PASS | 64 bytes |
| flash_read_8kb | PASS | 8192 bytes |
| data_write | PASS | 64 bytes |
| counter_stream | PASS | 5 items |
| counter_upload | PASS | 5 items |
Android Central (Pixel 5)
Connection interval: 30ms (Android negotiation)
| Test | Result | Details |
|---|---|---|
| flash_read_throughput | 56.7 KB/s | 10x 8192 bytes, 141.0 ms/call |
| flash_read_overhead | 90.1 ms/call | 1 byte x 20 calls |
| echo_roundtrip | 62.1 ms/call | 50 calls |
| data_write_throughput | 3.2 KB/s | 200 bytes x 20 calls, 61.8 ms/call |
| counter_stream (P→C) | 3.2 ms/item | 20 items in 64ms |
| counter_upload (C→P) | 5.5 ms/item | 20 items in 110ms |
| echo_basic | PASS | |
| echo_empty | PASS | |
| flash_read_basic | PASS | 64 bytes |
| flash_read_8kb | PASS | 8192 bytes |
| data_write | PASS | 64 bytes |
| counter_stream | PASS | 5 items |
| counter_upload | PASS | 5 items |
Performance Notes
Connection Interval Impact
The connection interval (CI) is the primary factor in round-trip latency. Each request–response cycle requires at least 2 connection events:
- macOS (bleak): CI = 15ms → ~30ms round-trip
- iOS (iPhone 16): CI = 30ms → ~60ms round-trip
- Android (Pixel 5): CI = 30ms → ~60ms round-trip, but highest throughput due to more packets per connection event
The peripheral advertises preferred CI of 15–30ms (PREF_MIN_INT=12, PREF_MAX_INT=24). The actual CI is determined by the Central’s OS.
Throughput Optimizations
- nanopb FT_CALLBACK: Streams flash data directly into protobuf encoding, saving 4KB static RAM
- Zero-copy response: Protobuf response is encoded directly at the container header offset
- No inter-packet delay: Containers are sent back-to-back
- Max 8KB per flash read: Optimal balance between latency and throughput