re: all savegame variation is in the header; slot region identical -- and my heuristic overstates
Splitting the same comparison at the documented slot-table boundary (save+136): the header holds 34 words and ALL 12 differing words, while the slot table holds 35 words and ZERO differences. The slot region is byte-identical between the two same-state saves, so the documented slot fields are untouched by the churn and a slot-region diff is meaningful where a whole-file diff is not. Also corrects my own framing from the previous commit. The slot region contains 6 words in the pointer value range that do NOT change across runs -- a pointer captured from a moving heap would not sit still, so those are data whose values merely land in 0x70-0x8F / 0xB0-0xBF. The value-range test alone does not identify a pointer; a third of what it flags here is not one. What identifies a pointer is being pointer-shaped AND varying, ideally with a shared constant delta. So '26% of the file is heap addresses' overstates it and the defensible figure is the 8 header words that are both. Left the earlier section in place with the correction after it: a value-range classifier on 32-bit words always has a false-positive rate, and quoting its raw count as a fact about the format is the error.
This commit is contained in:
@@ -631,3 +631,41 @@ in 12 words**, not 135.
|
||||
Worth stating because the inflated figure looked plausible: half the file
|
||||
changing between saves is exactly what one would expect if saves were dense
|
||||
state, and nothing about it invites a second look.
|
||||
|
||||
|
||||
## ✅ Refinement: every difference is in the HEADER; the slot region is identical
|
||||
|
||||
**Same day, one iteration later.** Splitting the same comparison at the
|
||||
documented slot-table boundary (`save+136`) sharpens the result considerably and
|
||||
corrects the framing above:
|
||||
|
||||
| region | words | pointer-shaped | **differ between same-state saves** |
|
||||
|---|---|---|---|
|
||||
| header, `< 0x88` | 34 | 12 | **12 — all of them** |
|
||||
| slot table, `≥ 0x88` | 35 | 6 | **0** |
|
||||
|
||||
**The slot region is byte-identical between the two saves.** Every one of the 12
|
||||
differing words lives in the header. That is a stronger and more useful statement
|
||||
than the pointer framing, and it means **the documented slot fields on this page
|
||||
are untouched by the churn** — they are stable state, and a diff of the slot
|
||||
region is meaningful in a way that a diff of the whole file is not.
|
||||
|
||||
### ⚠️ And my "pointer-shaped" heuristic has false positives
|
||||
|
||||
The slot region contains **6 words in the pointer value range that do not
|
||||
change** — `0x73777174`, `0x770F8877`, `0xBC2B75EF`, `0x8187F76B`,
|
||||
`0x7BE9C030`, `0x829F6B88`. A pointer captured from a moving heap would not sit
|
||||
still across two runs, so these are data whose values merely land in
|
||||
`0x70–0x8F`/`0xB0–0xBF`.
|
||||
|
||||
So the value-range test alone **does not identify a pointer** — a third of the
|
||||
words it flags here are not pointers. What identifies one is the *combination*
|
||||
of pointer-shaped **and** varying across runs, ideally with a shared constant
|
||||
delta as three of the header words have (`0x101080`). The previous section's
|
||||
"26 % of the file is heap addresses" overstates it on that basis; the defensible
|
||||
figure is the 8 header words that are both pointer-shaped and moving.
|
||||
|
||||
I am leaving the earlier section in place with this correction after it, because
|
||||
the mistake is instructive: a value-range classifier on 32-bit words will always
|
||||
have a false-positive rate, and quoting its raw count as a fact about the format
|
||||
is the error.
|
||||
Reference in New Issue
Block a user