CU25 — What only fed an answer that was kept is not run
Opened by a question about the notebook above: if widest is cached, should
sms and clean not be skipped? They should, and they were not.
The cache skipped the node whose own output was there and ran everything else anyway. On a graph fed by a dataset that is the expensive half — the file is read, the rows are tokenized, and none of it is looked at.
A name is knowable before anything runs
Section titled “A name is knowable before anything runs”key_for had already said so: the name this node’s output will have, before
it has one. Only the graph’s input is hashed by content; from there down a key
is made of keys. So the engine can name the whole plan with nothing executed,
ask which of those answers it already has, and then work backwards from the
leaves: a node whose answer is kept does not need its inputs.
Keeper::present is the question and it is new in the hole. The default is
honest and expensive — it reads them — and a store overrides it with
resolve_many: one scan, no fetches. Asking early has to be free or it is not
worth asking, which is the same price list CU20 wrote down.
Two places it gives up, both towards keeping a node rather than skipping one: a
.mapped() node is named out of the content of its items, so its names are
not knowable until it has them; and a node with no key at all is a miss for the
same reason it was never cached.
A slice nobody needs is not sent. The saving there is the round trip and not the work at the far end.
And it says so
Section titled “And it says so”Fact::Spared is a fact rather than an absence, because a node missing from a
record cannot be told from one that was never in the graph, and why is there no
time for clean is a question whoever reads a run will have. In the notebook
it reads:
{'fact': 'spared', 'node': 'sms'}{'fact': 'spared', 'node': 'clean'}{'fact': 'recalled', 'node': 'widest', 'key': 'sha256:c521a0…'}{'fact': 'finished', 'took_us': '155'}RunError::Vanished is the rare other end: something that was there when the
store was asked and gone when it was read, after what feeds it had already been
skipped because of that answer. It says what happened instead of leaving a
puzzle.
What the notebook caught
Section titled “What the notebook caught”Re-running examples/10-a-dataset.ipynb after writing this, the 19 MB toll had
gone from 121 ms to 245 ms. The pre-pass named the root and the walk named
it again, so the batch was hashed twice: asking early cost exactly what it
saves. The walk reuses the name that was already worked out, and it is back at
121 ms.
No test would have caught it — they all pass either way. It is the third real thing a notebook has found in this project, and the reason they are executed rather than written.
Questionnaire
Section titled “Questionnaire”The pruning (soma-core/tests/unit/execution.rs)
- what only fed an answer that was kept is not run
- and the answer is still the answer
- and it says so rather than leaving a hole in the record
- but what somebody else still reads is run
- a node that maps keeps everything above it
- and a slice nobody needs is not sent at all
End to end (soma-data/tests/unit/parquet.rs)
- the second run finds the answer under a name it could work out, and never opens the dataset