Skip to content

feat(coco)!: ASAPv1 codec with Rust-matching placement; drop the protobuf and gob formats - #92

Open
GordonYuanyc wants to merge 2 commits into
asapv1-only/infrafrom
asapv1-only/coco
Open

GordonYuanyc wants to merge 2 commits into
asapv1-only/infrafrom
asapv1-only/coco

Conversation

@GordonYuanyc

Copy link
Copy Markdown
Collaborator

Stacked on #85 (asapv1-only/infra). Part of the ASAPv1-only series: Go's CocoSketch gets an ASAPv1 codec. Decoding the spec's placement check required changing Go's Coco algorithm to match Rust's, not just adding a codec.

Changed (algorithm)

  • Buckets store the full string key. Row r places a key at HashIt(r, key) % cols (xxh3 seeded with seed_list[r] over the UTF-8 bytes, 64-bit modulo, no power-of-two constraint) — byte-identical to Rust's hash64_seeded over DataInput::Str across 1,958 key × row cases.
  • Insert follows Rust's Coco::insert: one pass over the d buckets; on no key match, the smallest bucket (free counts as 0) with a uniform reservoir tie-break takes the value, and the key wins it if it was free, else with probability v/val. "" and zero values are recorded (they were dropped).
  • New EstimateSubstring (like Rust's estimate_substring); Estimate stays exact-key. The package's previously failing substring tests now pass.

Added

  • (*CocoSketch).MarshalASAPv1 / UnmarshalASAPv1 (kind 0x0c 0x00); spec §3.12 decode rules incl. the placement check, duplicates, mass in free buckets and UTF-8. coco_3x7 passes CheckGolden, and each known cell's Estimate is checked.

Removed

  • proto/cocosketch and coco in the envelope (reserved 17; reserved "coco";); SerializePortable (portable.go); Coco's gob pair; the coco.pb producer in tests/cross_language.

Notes

  • InsertWithHash / QueryWithHash / EstimateHash (needed by common.Sketch and the ExponentialHistogram wrapper) count under the hex string of the hash, so Coco hashes internally despite common.Sketch's "must not hash internally" note. Follow-up: move that adapter into the EH package so CocoSketch is key-only like Rust.
  • A key that is not valid UTF-8 makes the sketch unencodable (documented on Insert).
  • Inserts are slower (d hashes per insert, as in Rust).

Verification (Go 1.24.9)

go build, go vet, gofmt, go test ./...; go test -count=20 ./sketches/CocoSketch/ passes. Known failures also on main: TestKLL_Reset_SubsequentInserts (flaky), tests/cross_language without XTEST_DIR. Implemented and reviewed by separate agents; review findings are addressed in the second commit.

🤖 Generated with Claude Code

GordonYuanyc and others added 2 commits October 2, 2026 01:14
CocoSketch encodes as ASAPv1 kind 0x0c 0x00: metadata carries the
standard hash spec (no seed index), rows and cols; the payload is the
row-major keys (nil for a free bucket) and values. Encode and decode
both reject zero or over-20-row geometry, mass in a free bucket, a key
outside the column its row hashes it to, and a key held twice.

Buckets now hold the full string key. Row r places a key at
xxh3(seed_list[r], key) % cols, and an insert scans all rows for the
key before claiming a free bucket. InsertWithHash, EstimateHash and
QueryWithHash count the key strconv.FormatUint(hash, 16), and
EstimateWithUDF passes the stored key.

Removed: SerializePortable, SerializeToBytes,
DeserializeCocoSketchFromBytes, the proto/cocosketch package, the coco
field of SketchEnvelope (number 17 reserved), and the coco.pb
cross-language producer. The golden submodule moves to 43b6cd2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Insert scans all d buckets for the key, otherwise adds v to the smallest
(a free bucket counts as 0, ties drawn uniformly) and the key takes that
bucket if it was free, else with probability v/val. The empty key and a
zero value are recorded. EstimateSubstring sums the buckets whose key
contains a partial key. The envelope reserves the name "coco".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant