summaryrefslogtreecommitdiff
path: root/experiments/ops-ReleaseFast.csv
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-25 18:41:18 -0300
committerGabriel Schneider <[email protected]>2026-08-25 18:41:18 -0300
commit1cef9c2e4bd873ebe13f5df635899231bcc467d2 (patch)
treece0a9495bc801666ff14da47f7a75728335cc442 /experiments/ops-ReleaseFast.csv
parentef6f3e460ddbf53a752807bcf10a0fec0a72da7f (diff)
downloadesp32p4-1cef9c2e4bd873ebe13f5df635899231bcc467d2.tar.gz
esp32p4-1cef9c2e4bd873ebe13f5df635899231bcc467d2.zip
A measuring instrument, and what it says about where the latency goes
"Too slow for interactive use" is a real complaint and not a number. This adds the number, and the number says the wire is innocent. ## The instrument `tools/perfproto.zig` is a small framed protocol - "P4", op, length, CRC-32 of the payload, payload - shared VERBATIM by the host tool and `examples/uartperf.zig`, so a frame one writes and the other parses cannot drift. It is imported as a module by both, not copied. The checksum is the whole point. RX overrun on this UART is undetected in hardware and uncounted in the driver, so a byte that never arrived is indistinguishable from a late one; a throughput figure that is not checksummed is a guess about how fast data was corrupted. `sink` accumulates a CRC over every payload byte the board received and `report` hands it back, so the host can prove that what arrived is what it sent. `tools/rtt.zig` is the two timing functions: `roundTrip` and `measure`. Round trip is to the FIRST response byte, deliberately. A renderer that starts drawing in 8 ms and finishes in 130 ms feels immediate; one that thinks for 130 ms and then draws in 8 ms feels broken; waiting for the wire to fall quiet cannot tell them apart. Time to the last byte is recorded separately as `settle`. Microseconds, because at 115200 one byte is 87 us and a millisecond clock quantises the answer into buckets eleven bytes wide. `tools/bench_main.zig` is `p4-bench`: `--link` for the ceiling, `--editor` for how much of it the editor uses, `--sweep` for one controlled variable at a time with `--csv` raw per-trial output. ## What it measured The link is essentially perfect: 11,496 B/s up and 11,413 B/s down, 99.8% of capacity in both directions, CRC verified over 32,768 B each way, zero corruption. Typing at 6 to 100 keys/s loses nothing and never uses more than 9% of the wire, so H5 - "typing loses input" - is refuted. Latency is compute per input event, not transmission. A 40-byte motion and a 206-byte insert-and-escape cost the SAME round trip to within 0.3 ms, across a five-fold range of output. That is why raising the baud cannot fix typing: there is almost no wire in it. And an edit costs the whole document. Round trip against characters already in the line is a straight line at 54.3 us per character per keystroke - 17.0 ms at an empty line, 25.6 ms at 160. On a ~90 MHz core that is ~5,000 cycles per character, far more than a copy alone, so the full-buffer copy the source does is accompanied by at least one more full pass. One controlled intervention: building the editor object ReleaseFast instead of ReleaseSmall cuts the fixed cost 13% and the per-character cost 36%, for 35% more flash (809,536 B of a 1,536,000 B partition). Its advantage grows with the document. Nothing else measured comes close to that ratio. ## Three bugs found while building it The responder printed garbage and looked dead: it read `.rodata` before evicting the bootloader's stale cache lines. `flushFlashCache` moved from `src/pardes/app.zig` to `soc.zig` with its measured evidence, since every application that touches `.rodata` after hand-over needs it and exactly one file knew that. Then it booted, printed its marker and went silent after ten seconds: `rst:0x10 (CHIP_LP_WDT_RESET)`. The bootloader arms the RTC watchdog and expects the application to take it over. Only the editor ever did. `serial.Port.drain()` drains INPUT, not output - so timing a transfer to it reported 202% of the wire's capacity and ate the reply. Added `flushOutput` (tcdrain), named so the two cannot be confused again. Also: Zig 0.16 emits an explicit `+` for a non-negative SIGNED integer whenever a width is given (std/Io/Writer.zig:1548-1559), which put a `+` in front of every number in the first tables. ## The report `experiments/report.typ` reads the raw CSVs and computes its own figures, so a re-run changes the document instead of contradicting it. It states five hypotheses, settles each against one experiment, and is explicit about the one that failed: the geometry sweep is confounded, because characters accumulated across conditions and the length experiment then proved that matters. It is reported as unsupported rather than dressed up as a result.
Diffstat (limited to 'experiments/ops-ReleaseFast.csv')
-rw-r--r--experiments/ops-ReleaseFast.csv50
1 files changed, 50 insertions, 0 deletions
diff --git a/experiments/ops-ReleaseFast.csv b/experiments/ops-ReleaseFast.csv
new file mode 100644
index 0000000..ea42b87
--- /dev/null
+++ b/experiments/ops-ReleaseFast.csv
@@ -0,0 +1,50 @@
+label,experiment,cols,rows,length,op,rep,rtt_us,settle_us,bytes
+ReleaseFast,ops,0,0,0,motion_h,0,14839,17388,40
+ReleaseFast,ops,0,0,0,motion_h,1,14767,17434,40
+ReleaseFast,ops,0,0,0,motion_h,2,14721,17372,40
+ReleaseFast,ops,0,0,0,motion_h,3,14715,17395,40
+ReleaseFast,ops,0,0,0,motion_h,4,14695,17281,40
+ReleaseFast,ops,0,0,0,motion_h,5,14703,17284,40
+ReleaseFast,ops,0,0,0,motion_h,6,14717,17393,40
+ReleaseFast,ops,0,0,0,motion_l,0,14742,17302,40
+ReleaseFast,ops,0,0,0,motion_l,1,14746,17425,40
+ReleaseFast,ops,0,0,0,motion_l,2,14727,17342,40
+ReleaseFast,ops,0,0,0,motion_l,3,14723,17272,40
+ReleaseFast,ops,0,0,0,motion_l,4,14876,17380,40
+ReleaseFast,ops,0,0,0,motion_l,5,14704,17341,40
+ReleaseFast,ops,0,0,0,motion_l,6,14746,17328,40
+ReleaseFast,ops,0,0,0,line_start,0,14767,17478,40
+ReleaseFast,ops,0,0,0,line_start,1,14760,17396,40
+ReleaseFast,ops,0,0,0,line_start,2,14735,17355,40
+ReleaseFast,ops,0,0,0,line_start,3,14701,17364,40
+ReleaseFast,ops,0,0,0,line_start,4,14710,17286,40
+ReleaseFast,ops,0,0,0,line_start,5,14771,17453,40
+ReleaseFast,ops,0,0,0,line_start,6,14751,17226,40
+ReleaseFast,ops,0,0,0,line_end,0,14783,17424,40
+ReleaseFast,ops,0,0,0,line_end,1,14807,17443,40
+ReleaseFast,ops,0,0,0,line_end,2,14773,17284,40
+ReleaseFast,ops,0,0,0,line_end,3,14737,17408,40
+ReleaseFast,ops,0,0,0,line_end,4,14769,17508,40
+ReleaseFast,ops,0,0,0,line_end,5,14732,17412,40
+ReleaseFast,ops,0,0,0,line_end,6,14750,17268,40
+ReleaseFast,ops,0,0,0,insert_esc,0,14827,42161,265
+ReleaseFast,ops,0,0,0,insert_esc,1,14908,36678,204
+ReleaseFast,ops,0,0,0,insert_esc,2,14983,36759,206
+ReleaseFast,ops,0,0,0,insert_esc,3,14988,36851,206
+ReleaseFast,ops,0,0,0,insert_esc,4,14906,36822,206
+ReleaseFast,ops,0,0,0,insert_esc,5,15050,36865,206
+ReleaseFast,ops,0,0,0,insert_esc,6,15059,36952,206
+ReleaseFast,ops,0,0,0,repaint_39,0,14926,32405,81
+ReleaseFast,ops,0,0,0,repaint_39,1,14936,32122,80
+ReleaseFast,ops,0,0,0,repaint_39,2,14895,32294,80
+ReleaseFast,ops,0,0,0,repaint_39,3,14975,32342,80
+ReleaseFast,ops,0,0,0,repaint_39,4,15026,32363,80
+ReleaseFast,ops,0,0,0,repaint_39,5,14968,32224,80
+ReleaseFast,ops,0,0,0,repaint_39,6,14885,32342,80
+ReleaseFast,ops,0,0,0,repaint_40,0,14876,32419,80
+ReleaseFast,ops,0,0,0,repaint_40,1,14866,32211,80
+ReleaseFast,ops,0,0,0,repaint_40,2,14868,32173,80
+ReleaseFast,ops,0,0,0,repaint_40,3,14888,32329,80
+ReleaseFast,ops,0,0,0,repaint_40,4,14869,32208,80
+ReleaseFast,ops,0,0,0,repaint_40,5,14863,32277,80
+ReleaseFast,ops,0,0,0,repaint_40,6,14876,32143,80