summaryrefslogtreecommitdiff
path: root/src/host_io.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-25 19:16:11 -0300
committerGabriel Schneider <[email protected]>2026-08-25 19:16:11 -0300
commitc0c722167a7c4d370c09eab4be0f777cef43feb4 (patch)
tree868fc651f849814adf01b088e8b8f392de956e37 /src/host_io.zig
parent939e3a7288d6782139cac36f091ccd1d41cdfc0a (diff)
downloadpardes-c0c722167a7c4d370c09eab4be0f777cef43feb4.tar.gz
pardes-c0c722167a7c4d370c09eab4be0f777cef43feb4.zip
Bound the edit path's document scans, and find out they were never the problem
The measurement said a keystroke costs 54 us per character already in the line. The source said why: `insertAt` called `lineCount` - `std.mem.count` over every byte - TWICE merely to clamp a row, and then `spliceAlloc` allocated and copied the whole document. Three whole-document passes before one character can be inserted, which fits a linear slope exactly. So it was fixed. `modal.lineSpan` finds a row's byte span in ONE scan that stops at that row, and `insertAt` uses it; a full count is paid only on the rare clamping path where the cursor is past the end. Two tests pin the equivalence, including the edges that make line counting awkward - an empty document, a trailing newline (its own empty last line), and a row past the end. The first version of `lineSpan` disagreed with `lineCount` about an empty document and the test caught it. On the host harness this is a real win, reproduced over three independent runs at matched sample counts: edit-char 1k lines 50k lines 300k lines before 730 us 2996 us 15030 us after 721 us 2414 us 10955 us ratio 0.98x 0.79-0.82x 0.78-0.83x Every operation I did not touch stayed at 1.00x, which is better evidence than any single cell. On the board it changed NOTHING. The slope was 54.3 us/char before and 54.0 after, a ratio of 1.00 over 5 conditions x 7 trials. Not a contradiction - the same fact seen twice. The removed passes are O(document), and this board's document is a few hundred BYTES, so two scans of it cost nothing worth measuring. ## Where the time actually goes `-Dprof` times the two phases on the die with the cycle counter around `pardes_p4_input` and `pardes_p4_render`: chars in line input (parse+edit) render 1 220 us 14804 us 80 212 us 17114 us 240 250 us 24615 us Input is FLAT at ~220 us - 1.5% of a keystroke - and does not grow with the document at all. The ~15 ms floor and every microsecond of the slope are inside `render`. The edit path could be made free and nobody would notice. `soc.flushFlashCache`'s home in soc.zig is what let the profiling build exist at all alongside the responder; `-Dprof` defaults off because it puts a line on the wire per frame, which is the resource being measured. ## The report `experiments/report.typ` gains Experiment 3 and, more importantly, a correction: Experiment 2's mechanism claim was wrong and now says so, with the disproof next to it. The ranked recommendations are reordered - the renderer is now #1 and the change this commit makes is listed unranked, because on this target it buys nothing, which is exactly why it is worth recording. The position table earns its place there too: in a fixed 320-character line, an insert at column 320 costs 33.9 ms and emits 28 bytes, while one at column 0 costs 26.0 ms and emits 81. Output size and latency are not merely uncorrelated on this board, they are inverted - which is the signature of a walk from the start of a line, and the next thing to go looking for. The lesson is the one the instrument exists to enforce. A plausible mechanism, read off the source and consistent with the shape of the data, was wrong about where the time went, and only a measurement inside the firmware could say so.
Diffstat (limited to 'src/host_io.zig')
0 files changed, 0 insertions, 0 deletions