Expand description
A device that counts what a driver asks of it.
§Why this is in the shared crate rather than a test file
Every driver in this family is about to be measured and then made faster, and a measurement is only worth having if the drivers can be compared against each other and against themselves later. Two drivers each counting reads with their own wrapper would produce two numbers that look alike and are not: one might count a read of a whole extent as one, the other as one per block, and nothing in either number would say so.
One instrument, in the crate every driver already depends on. It
wraps a BlockRead and forwards every call, so a driver mounted
on it behaves exactly as it would otherwise.
§What the numbers mean
- reads — calls to
BlockRead::read_at. This is the number a cache moves: a metadata block read twice is two reads here and one after a cache is put underneath. - bytes — the size of every buffer those calls asked to have filled. This is not the same number as the read count, and that is why both are here: a driver that reads a 4 KiB block to look at 8 bytes of it is one read either way, and only the byte count shows the 4 KiB it asked the device for to use 8.
Both are worth having. A change that halves reads and doubles bytes is a readahead that guessed wrong, and one number alone would call it a win.
§Both numbers are what was asked for, not what moved
bytes is the buffer a call presented, added before the call is
forwarded and never adjusted afterwards, so a read the device
refuses contributes its whole buffer. That is the same rule as
reads, for the same reason: a driver looping on an out-of-range
offset is exactly the shape these numbers exist to make visible, and
a counter that sat still through it would hide the loop.
It is worth being plain that this is the only rule available, rather
than a convenience. Bytes-moved is not reachable through
BlockRead at all: BlockRead::read_at returns Result<()>
and carries no transfer count, so the only place a real figure ever
appears is got inside crate::Error::ShortRead — off the
success path, and absent from the other errors an over-read can
produce. Counting only on Ok would not recover it either, because
a refused read is not reliably a transfer of nothing: a
crate::FileDevice copies the readable prefix into the buffer
before reporting the shortfall, so a 64-byte request against a
16-byte file really moves 16 bytes, while the same request against
an in-memory device moves none. Counting on Ok reports 0 for both;
this counter reports 64 for both.
Reporting the request is therefore the one answer that does not depend on which device happens to be underneath, which is what makes two drivers’ numbers comparable — the whole point of the module. The price is that these counters are not a transfer total for a run with failed reads in it, and should not be read as one.
Structs§
- Counting
Device - Wraps a device and counts the reads passing through it.