docs(tinygo): correct the xxh3 limitation and point to murmur3 - #799
Conversation
|
So, it might be worth pointing out that I had a pure let-go implementation of xxh3 that might be worth trying the aot on to see if it can't provide that fingerprint hash. |
Yeah, thanks for the reminder. I remember you had that. Would be neat to see how it goes with aot. I'll take a look! |
|
@nnunley I tried it. The pure xxh3 is the What AOT does for it: What it cannot do is change the integer width. The lowerer maps
Linking the lowered package into a So a 64-bit hash under TinyGo wasm needs The probe did turn up one gap on the let-go side: |
The bullet described a pure-Go substitute hash that is never linked. `pkg/rt/interop_xxh3.go` is gated `//go:build !tinygo`, so a TinyGo build has no `xxh3` namespace at all: a program calling `xxh3/*` gets nil and fails at the call site rather than producing different digests. It also had the determinism story backwards. `pkg/rt/hash_murmur3.go` is untagged and registered on every build, and masks results to 31 bits so a value is identical on 64-bit native and 32-bit wasm — the header comment says so explicitly. murmur3 is the hash that removes the divergence, not one that introduces it, so the guide should name it as the port target instead of warning about a determinism domain to accept. Found by building a downstream program whose seed fold calls `xxh3-64`: it reaches its title screen under TinyGo and then dies on the nil namespace. After swapping to `murmur3` the program runs, and its generated world is byte-identical between the TinyGo wasm build and the stock-Go wasm build at a fixed seed. Docs only; no code changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8afed0d to
067888a
Compare
What this changes
The TinyGo guide's
xxh3bullet describes a substitution that does not happen. It currently reads:Two claims there send a reader the wrong way.
No substitute is linked.
pkg/rt/interop_xxh3.gocarries//go:build !tinygo, so a TinyGo build has noxxh3namespace. A program callingxxh3/*does not get different digests; it gets nil and fails at the call site.murmur3is the portable hash, not a divergent one.pkg/rt/hash_murmur3.gois untagged and registered on every build, and it masks results to 31 bits so a value is identical on 64-bit native and 32-bit wasm. Its own header states this intent. The current text points at a determinism domain to avoid, when the available hash is the one that removes the divergence.The replacement bullet says the namespace is absent, names
murmur3as the call to make instead, notes that the surface matches (Hash,HashSeed,HashString,HashStringSeed), and gives the 31-bit masking so the reader can see how it composes with theint-width limitation directly above it.How this surfaced
Building a real program: a game whose determinism layer is keyed on a seed fold. Under TinyGo it builds and reaches its title screen, then dies:
The guide sends you looking for a digest mismatch. The failure is a missing namespace, and the fix is a one-token swap to
murmur3. After that swap the game runs, and its generated world is byte-identical between the TinyGo wasm build (32-bitint) and the stock-Go wasm build (64-bitint): same sha256 over the rendered dungeon at a fixed seed. That is the masking doing what its implementation comment describes.Verification
!tinygotag oninterop_xxh3.goand the absence of a tag onhash_murmur3.goboth read offorigin/main.murmur3/HashSeedexercised on a native build; results land inside 31 bits.origin/mainTinyGo wasm build.Docs only. No code changes, nothing to regenerate, no CI surface touched.