Repository navigation
perf: size the read chunk to the probe's contact window - #17
Merged
Merged
Conversation
Measured where a 32MB read actually spends its time, rather than assuming:
USB traffic at 121 KiB/s SPI : 246 KiB/s = 2.0 Mbit/s of a 12 Mbit/s
full-speed ceiling, so 17% used
SPI bits/s at 121 KiB/s : 0.99 Mbit/s
USB is not the limit. The ~1 MHz SPI clock is, and we never configure it
(init sends only CMD_UIO_STREAM pin direction, no stream-speed command), so
we run at the device's power-on default. That is real headroom and it is left
alone deliberately: the value is unmeasured, and a faster clock degrades
signal integrity on exactly the marginal probe this is all for. It wants a
CS-deasserted bench on real silicon, not a guess from reference source.
The number that actually decides whether a marginal probe makes progress is
not throughput at all: a chunk only counts if it finishes inside ONE unbroken
contact window. At 121 KiB/s, with backup chunks read twice:
64KB -> 1.058s of held contact 8KB -> 0.132s
32KB -> 0.529s 4KB -> 0.066s
16KB -> 0.264s
A probe that cannot hold 1.06s makes NO progress at 64KB, however many
windows it gets: every chunk dies partway and is discarded. That is a cliff,
not a slope, and no amount of clock speed climbs it. Measured contact on the
board is 1 sample in 32.
So make it tunable: `ratchet read --chunk-kb N`, default 64 (unchanged).
Changing it restarts the dump, because the sidecar records the stride and
refuses to mix two griddings of one chip. That rejection is the existing
paranoia and it is correct here: bytes banked at one stride were never
verified at another.
Test observes the grid the READ wrote, via the sidecar it saves on failure.
The first version of this test asserted against a ResumeState the test itself
built, and stayed green when set_read_chunk was mutated to ignore its
argument: it proved nothing about the read. Both mutations now fail it
(setter ignores its argument; read loop uses the const instead of the field).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Measured first, rather than assuming
USB is not the limit. The ~1 MHz SPI clock is.
The headroom I am deliberately NOT taking
We never configure the CH341A's stream clock. Init sends only
CMD_UIO_STREAMpin direction; there is no stream-speed command anywhere in the backend, so we run at the device's power-on default. That is genuine unexploited headroom.It is left alone on purpose:
Worth doing, with a bench, on real silicon. Not worth guessing.
The number that actually matters
Throughput is not the binding constraint. A chunk only counts if it finishes inside ONE unbroken contact window. At 121 KiB/s, with backup chunks read twice:
A probe that cannot hold for 1.06s makes zero progress at 64KB, no matter how many windows it gets: every chunk dies partway and is discarded. That is a cliff, not a slope, and no clock speed climbs it. Measured contact on the board is 1 sample in 32.
So:
ratchet read --chunk-kb N, default 64 (no behaviour change unless asked for).Changing it restarts the dump. The sidecar records the stride and refuses to mix two griddings of one chip; that rejection is pre-existing paranoia and it is right here, because bytes banked at one stride were never verified at another.
The test was weak and mutation testing caught it
The first version asserted against a
ResumeStatethe test itself constructed. It proved nothing about the read, and stayed green whenset_read_chunkwas mutated to ignore its argument: a decorative test for a decorative knob.Rewritten to observe the grid the read wrote, via the sidecar it saves on failure. Both mutations now fail it:
set_read_chunkignores its argumentCLI bounds verified end to end:
--chunk-kb 99999and--chunk-kb 0both rejected.Verification
cargo test --workspace501 pass,clippy --workspace --all-targets -D warningsclean,fmt --checkclean.