Skip to content

Commit cc775f5

Browse files
DavidCozensclaude
andcommitted
feat: halve the record buffer now the store holds the backlog
The ring is sized in records, so doubling the message cap doubled its cost. Four records is enough to absorb a burst logged while the service task is sending; the store, not the ring, is what holds a backlog. Flash +11,980 B (unchanged) RAM +7,384 B (-2,056) Log stack +704 B (unchanged) Service +992 B (unchanged) Static RAM is the only figure that moves, and it is exactly four records at the cap plus a two-byte length prefix each. Nothing else is affected: the ring bounds how many records can be in flight, not how large one may be. Taken with the cap rise, the pair costs 248 bytes. The ring ends up 8 bytes smaller than it was before the cap moved — four records at 512 is less than eight at 256 — so what is actually being paid for is the store's single record buffer, which follows the cap and cannot be halved. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 9fb81d6 commit cc775f5

5 files changed

Lines changed: 39 additions & 23 deletions

File tree

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ It builds on a baseline that simulates the sort of device you might be adding th
1010
measures itself: see [docs/baseline.md](docs/baseline.md) for what the baseline is, how the
1111
figures are made, and how to run it.
1212

13-
## This stage — Larger cap
13+
## This stage — Smaller ring
1414

15-
The message cap doubles to 512 bytes. Three SD-ELEMENTs had already taken a short record close to
16-
the old ceiling, and the two counters it carries are 32-bit — at full width the same record would
17-
cross it and start truncating.
15+
The ring holds four records instead of eight. It is sized in records, so doubling the cap doubled
16+
what it cost — and four is enough to absorb what gets logged while the service task is sending,
17+
because the store rather than the ring is what holds a backlog.
1818

19-
The cost is almost all RAM, because the cap sizes three things at once: the ring, the store's
20-
record buffer, and the deepest single demand the formatter makes of whichever task calls it.
19+
It gives back almost everything the cap rise took. Nothing else moves: the ring bounds how many
20+
records can be in flight, not how large one may be.
2121

2222
<!-- STAGE-COST:START (generated by scripts/gen-cost-table.py — do not edit by hand) -->
2323

24-
**Cost above baseline: Flash +11,980 B, RAM +9,440 B.**
24+
**Cost above baseline: Flash +11,980 B, RAM +7,384 B.**
2525

2626
<!-- STAGE-COST:END -->
2727

@@ -48,6 +48,7 @@ committed as [`run-report.md`](run-report.md), and rewritten by every stage.
4848
| File store | records that survive a failed send, spooled to disk with a checksum at rest | +11,576 | +7,092 |
4949
| Origin | the device named in the record itself, not inferred from the source address | +11,972 | +7,136 |
5050
| Larger cap | headroom for the grown record, so full-width counters cannot push it into truncation | +11,980 | +9,440 |
51+
| Smaller ring | most of the cap rise given back, now the store rather than the ring holds a backlog | +11,980 | +7,384 |
5152

5253
*Deltas are bytes above the baseline, which is itself Flash 350,308 B, RAM 111,192 B.*
5354

app/syslog/Syslog.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@
4747
#define SYSLOG_COLLECTOR_HOST "10.0.2.2"
4848
#define SYSLOG_COLLECTOR_PORT ((uint16_t) 5601U)
4949

50-
/* Depth enough to absorb a burst while the sender is busy, without sizing for a
51-
* backlog the store is there to hold. */
52-
#define SYSLOG_BUFFER_RECORDS 8U
50+
/* Absorbs records logged while the service task is busy sending. Many devices can
51+
* reduce this further: the store holds the backlog, so the ring only has to cover
52+
* a burst. */
53+
#define SYSLOG_BUFFER_RECORDS 4U
5354

5455
/* One "<prefix>NN.log" per block, on the volume the device already mounts. */
5556
#define SYSLOG_STORE_PREFIX "syslog"

measurements/buffer-halve.csv

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# buffer-halve figures (bytes) — captured by scripts/run.sh (CAPTURE=1).
2+
# The device reads measurements/Baseline.csv as its frozen baseline and reports current-minus-Baseline.
3+
flash_text,361648
4+
flash_data,640
5+
static_bss,117936
6+
heap_used,4440
7+
mbedtls_peak,21340
8+
mbedtls_free,11428
9+
lwip_mem_free,7576
10+
lwip_pbufs_free,13
11+
stack_log,824
12+
stack_service,1044
13+
stack_harness,2848

measurements/stages.tsv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ time-quality Time quality a timestamp the collector knows how far to trust, and
2323
file-store File store records that survive a failed send, spooled to disk with a checksum at rest
2424
origin Origin the device named in the record itself, not inferred from the source address
2525
cap-rise Larger cap headroom for the grown record, so full-width counters cannot push it into truncation
26+
buffer-halve Smaller ring most of the cap rise given back, now the store rather than the ring holds a backlog

run-report.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# solid-syslog-example — run (cap-rise)
1+
# solid-syslog-example — run (buffer-halve)
22

33
## Device (self-measured)
44

@@ -12,12 +12,12 @@
1212
[report] key,current,baseline,used_above_baseline
1313
[report] flash_text,361648,349992,11656
1414
[report] flash_data,640,316,324
15-
[report] static_bss,119992,110876,9116
15+
[report] static_bss,117936,110876,7060
1616
[report] heap_used,4440,4440,0
17-
[report] mbedtls_peak,21332,21332,0
18-
[report] mbedtls_free,11436,11436,0
17+
[report] mbedtls_peak,21340,21332,8
18+
[report] mbedtls_free,11428,11436,-8
1919
[report] lwip_mem_free,7576,7576,0
20-
[report] lwip_pbufs_free,14,14,0
20+
[report] lwip_pbufs_free,13,14,-1
2121
[report] stack_log,824,120,704
2222
[report] stack_service,1044,52,992
2323
[report] stack_harness,2848,2840,8
@@ -29,7 +29,7 @@
2929

3030
```text
3131
text data bss dec hex filename
32-
361640 648 119992 482280 75be8 /w/build/baseline-cross/baseline.elf
32+
361640 648 117936 480224 753e0 /w/build/baseline-cross/baseline.elf
3333
```
3434

3535
## Listeners (proved before the device ran)
@@ -47,21 +47,21 @@
4747
## Collector (syslog-ng) received
4848

4949
```text
50-
wire <134>1 2026-07-29T08:25:48.280000Z 10.0.2.15 solid-syslog-example - BOOT [meta sequenceId="1" sysUpTime="228"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] device started
51-
parsed PRIORITY=134 TIMESTAMP=2026-07-29T08:25:48+00:00 HOSTNAME=10.0.2.15 APP_NAME=solid-syslog-example PROCID= MSGID=BOOT STRUCTURED_DATA=[meta sequenceId="1" sysUpTime="228"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] MSG=device started
50+
wire <134>1 2026-07-29T08:29:37.410000Z 10.0.2.15 solid-syslog-example - BOOT [meta sequenceId="1" sysUpTime="241"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] device started
51+
parsed PRIORITY=134 TIMESTAMP=2026-07-29T08:29:37+00:00 HOSTNAME=10.0.2.15 APP_NAME=solid-syslog-example PROCID= MSGID=BOOT STRUCTURED_DATA=[meta sequenceId="1" sysUpTime="241"][timeQuality tzKnown="1" isSynced="0"][origin software="solid-syslog-example" swVersion="0.1.0" enterpriseId="32473"] MSG=device started
5252
```
5353

54-
## Self-check (vs measurements/cap-rise.csv)
54+
## Self-check (vs measurements/buffer-halve.csv)
5555

5656
```text
5757
OK flash_text: 361648 (expected 361648, Δ0)
5858
OK flash_data: 640 (expected 640, Δ0)
59-
OK static_bss: 119992 (expected 119992, Δ0)
59+
OK static_bss: 117936 (expected 117936, Δ0)
6060
OK heap_used: 4440 (expected 4440, Δ0)
61-
OK mbedtls_peak: 21332 (expected 21332, Δ0)
62-
OK mbedtls_free: 11436 (expected 11436, Δ0)
61+
OK mbedtls_peak: 21340 (expected 21340, Δ0)
62+
OK mbedtls_free: 11428 (expected 11428, Δ0)
6363
OK lwip_mem_free: 7576 (expected 7576, Δ0)
64-
OK lwip_pbufs_free: 14 (expected 14, Δ0)
64+
OK lwip_pbufs_free: 13 (expected 13, Δ0)
6565
OK stack_log: 824 (expected 824, Δ0)
6666
OK stack_service: 1044 (expected 1044, Δ0)
6767
OK stack_harness: 2848 (expected 2848, Δ0)

0 commit comments

Comments
 (0)