Performance¶
Measured on the boards by the test firmware's bench and burst commands, collected by firmware/bench.py, which also reads the footprint from each build's link map. Rerun it to update this page.
| Board | Measured | Firmware |
|---|---|---|
| nucleo_c071rb (Cortex-M0+, 48 MHz) | 2026-10-27 | f4fab54 |
| nucleo_l452re_p (Cortex-M4F, 80 MHz) | 2026-10-27 | f4fab54 |
| stm32wba55g_dk1 (Cortex-M33, 32 MHz) | 2026-10-27 | f4fab54 |
Bytes per log¶
What one log statement sends: ucLog's frame (the format string's address, the arguments in binary, COBS and the frame delimiter), against the same message formatted as text with its line end. Neither counts a timestamp, level or file name: ucLog's hosts get those from the logdata; a text log would usually add them.
| Statement | ucLog | text |
|---|---|---|
LOG_INFO("bench: no arguments"); |
7 B | 21 B |
LOG_INFO("bench: count %d", count); |
11 B | 19 B |
LOG_INFO("bench: x=%d y=%d", x, y); |
15 B | 20 B |
LOG_INFO("bench: %d %d %d %d", count, x, y, z); |
23 B | 28 B |
LOG_INFO("bench: temp %.2f", temp); |
15 B | 19 B |
LOG_INFO("bench: ratio %f", ratio); |
15 B | 23 B |
LOG_INFO("bench: name %s", name); |
16 B | 22 B |
LOG_INFO("bench: %s count=%d temp=%.1f ratio=%f", name, count, temp, ratio); |
36 B | 53 B |
Time per log¶
CPU cycles for the call (the fastest of 32, interrupts on): ucLog's call encodes the frame, copies it into the log ring and starts sending it; snprintf (newlib-nano) only formats the text, which then still has to be sent. On a 1 Mbaud UART each byte takes 10 µs, so the bytes above matter as much as the cycles.
| Statement | nucleo_c071rb: ucLog | snprintf | nucleo_l452re_p: ucLog | snprintf | stm32wba55g_dk1: ucLog | snprintf |
|---|---|---|---|---|---|---|
args0 |
721 (15.0 µs) | 252 (5.2 µs) | 706 (8.8 µs) | 194 (2.4 µs) | 1229 (38.4 µs) | 163 (5.1 µs) |
int1 |
953 (19.9 µs) | 1591 (33.1 µs) | 929 (11.6 µs) | 1467 (18.3 µs) | 1573 (49.2 µs) | 1136 (35.5 µs) |
int2 |
1204 (25.1 µs) | 2509 (52.3 µs) | 1084 (13.6 µs) | 2320 (29.0 µs) | 1716 (53.6 µs) | 2271 (71.0 µs) |
int4 |
1567 (32.6 µs) | 4967 (103.5 µs) | 1344 (16.8 µs) | 4183 (52.3 µs) | 1991 (62.2 µs) | 5337 (166.8 µs) |
float1 |
1153 (24.0 µs) | 9994 (208.2 µs) | 1089 (13.6 µs) | 6751 (84.4 µs) | 1719 (53.7 µs) | 5751 (179.7 µs) |
double1 |
1128 (23.5 µs) | 10906 (227.2 µs) | 1061 (13.3 µs) | 6412 (80.1 µs) | 1713 (53.5 µs) | 5857 (183.0 µs) |
str1 |
1319 (27.5 µs) | 1479 (30.8 µs) | 1280 (16.0 µs) | 1462 (18.3 µs) | 1862 (58.2 µs) | 2001 (62.5 µs) |
mixed4 |
2318 (48.3 µs) | 22002 (458.4 µs) | 2014 (25.2 µs) | 14615 (182.7 µs) | 2553 (79.8 µs) | 15108 (472.1 µs) |
Throughput¶
A burst of 2000 logs as fast as the link takes them (burst 2000, 19 bytes per log), and the median round trip of 16 bytes from a script through the hub to the device and back.
| Board | Link | Bytes/s | Logs/s | Round trip |
|---|---|---|---|---|
| nucleo_c071rb | UART, 1 Mbaud | 100,000 | 5,263 | 2.0 ms |
| nucleo_c071rb | USB CDC | 463,415 | 24,390 | 1.0 ms |
| nucleo_c071rb | USB HID | 62,914 | 3,311 | 9.09 ms |
| nucleo_l452re_p | UART, 1 Mbaud | 100,000 | 5,263 | 2.18 ms |
| stm32wba55g_dk1 | UART, 1 Mbaud | 100,000 | 5,263 | 1.0 ms |
| stm32wba55g_dk1 | Bluetooth LE | 95,960 | 5,051 | 30.03 ms |
Footprint¶
The library as linked into the test firmware (-Os, unused functions removed), from the link map. RAM includes the log ring, which is configurable (LOG_TX_BUF_SIZE). The format strings stay in the ELF and cost no flash. For comparison: what snprintf adds to a program, with integers only and with floats.
| Board | ucLog flash | ucLog RAM (log ring) | Format strings, not in flash | snprintf | snprintf with floats |
|---|---|---|---|---|---|
| nucleo_c071rb | 6.6 KiB | 9.5 KiB (4.0 KiB) | 5.1 KiB | 2.8 KiB | 21.8 KiB |
| nucleo_l452re_p | 6.5 KiB | 14.4 KiB (8.0 KiB) | 5.3 KiB | 2.7 KiB | 15.2 KiB |
| stm32wba55g_dk1 | 6.6 KiB | 14.4 KiB (8.0 KiB) | 5.8 KiB | 2.5 KiB | 15.0 KiB |
By object (flash / RAM, bytes):
| Object | nucleo_c071rb | nucleo_l452re_p | stm32wba55g_dk1 |
|---|---|---|---|
log.o |
2297 / 9243 | 2273 / 13339 | 2273 / 13339 |
log_plot.o |
848 / 0 | 890 / 0 | 890 / 0 |
semihost.o |
1176 / 512 | 1108 / 1443 | 1108 / 1443 |
syscalls.o |
272 / 0 | 248 / 0 | 248 / 0 |
cb.o |
162 / 0 | 154 / 0 | 208 / 0 |
cobs.o |
98 / 0 | 92 / 0 | 92 / 0 |
cbor.o |
1888 / 0 | 1896 / 0 | 1894 / 0 |
log.o is the core; log_plot.o is only linked with plots; semihost.o and syscalls.o only with semihost (files and stdio on the host); cb.o, cobs.o, cbor.o are ucComm.
On the host¶
Logs decoded per second, from frames recorded off the board:
| Board | Python library | uclog decode |
Machine |
|---|---|---|---|
| nucleo_c071rb | 261,231 | 369,268 | Darwin arm64, Python 3.14.7 |
| nucleo_l452re_p | 179,385 | 746,211 | Darwin arm64, Python 3.14.7 |
| stm32wba55g_dk1 | 201,195 | 727,801 | Darwin arm64, Python 3.14.7 |