Skip to content

feat(intchunk): cold INT best-of-N lossless value chunk codec - #434

Merged
zzylol merged 2 commits into
mainfrom
feat/cold-int-chunk-codec
May 25, 2026
Merged

zzylol merged 2 commits into
mainfrom
feat/cold-int-chunk-codec

Conversation

@zzylol

@zzylol zzylol commented May 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements PR5 of the holistic-compression design (DESIGN.md §1.2-1.4 + §8): a standalone, lossless cold-tier raw-value chunk codec at asap-gorilla-go/intchunk/. This is a self-contained library + tests + benchmark only. It is not wired into the agent encoder or the merger — integration (agent encode + decode-on-read StoreAPI + shared-ts) is the follow-up PR6/PR7.

Codec

Per-series-per-block best-of-N, all three candidates lossless; the smallest wins:

tag codec for
0 GORILLA_XOR lossless float64 via prometheus/tsdb/chunkenc XOR (Gorilla). Always valid; fallback for true high-precision floats.
1 INT_FOR_DELTA float→int64 via decimal scale exp, frame-of-reference (subtract base), delta, fixed-width bit-pack. Gauges.
2 INT_FOR_DOD same scale+FOR but delta-of-delta. Counters/monotonic + the timestamp column.

Decimal-exactness guard (tryScaleToInt64) — the load-bearing trap-avoider: an INT_* candidate is only produced when float→int64→float round-trips bit-exactly at the chosen scale. Decode divides by the decimal-exact 10^e (never a rounded reciprocal — using a reciprocal multiply wrongly rejected most fixed-decimal series and inflated the exponent). Otherwise only Gorilla is offered.

Overflow chunk-cut (§1.4/§3 drift→re-base): a residual exceeding the integer width ends the chunk and starts a fresh one with a new base; each chunk is self-contained / independently decodable.

Header (§1.2): codec_tag:u8, n_samples:uvarint, timestamps as t0 + delta-of-delta varints; INT tags add scale_exp:i8, base:zigzag-varint, first_residual.

API surface

func Encode(samples []Sample) (EncodeResult, error)   // best-of-N; Chunks may be >1 on overflow cut
func DecodeChunk(chunk []byte) ([]Sample, error)
func DecodeChunks(chunks [][]byte) ([]Sample, error)
func PeekTag(chunk []byte) (CodecTag, error)
type Sample struct { T int64; V float64 }
type EncodeResult struct { Tag CodecTag; Chunks [][]byte; Bytes int }

Files: codec.go (header/tags/varint/zigzag/bit-pack), scale.go (exactness guard), intchunk.go (INT codecs + ts column + overflow cut), gorilla.go (XOR wrapper), bestofn.go (driver), codec_test.go, bench_test.go. Only new dep used is chunkenc (already transitive via prometheus/prometheus); go.mod/go.sum unchanged.

Benchmark (block=1000, real Serf datasets — bits/sample)

series gor b/s int b/s gor/int best-of-N winner
City-temp (fixdec) 55.17 19.57 2.82× INT_FOR_DELTA
Dew-point-temp 54.98 18.73 2.94× INT_FOR_DELTA
Stocks-USA 43.92 16.11 2.73× INT_FOR_DELTA
Wind-Speed 56.56 15.65 3.61× INT_FOR_DELTA
Motor-temp (float32) 21.50 47.85 0.45× GORILLA_XOR
Air-pressure (hi-prec) 15.55 19.46 0.80× GORILLA_XOR

Class roll-up verdict: fixed-decimal gor/int ≈ 2.22× → INT wins; high-precision float → Gorilla wins (best-of-N correctly falls back). The simpler FOR+fixed-width pack lands ~2.2-3.6× vs the design's VM-adaptive ~4.8× target, which is the deliberately-simple §1.3 tradeoff. Micro-bench: encode ~194 ns/sample, decode ~52 ns/sample.

Test plan

  • go test ./... green (whole asap-gorilla-go module)
  • lossless round-trip: gauges, monotonic counters, high-precision floats, constants, negatives/zero, single/two-sample, irregular timestamps, randomized fuzz (200 iters)
  • best-of-N picks the smallest valid candidate (asserted vs direct candidate sizes)
  • exactness guard rejects 15+ sig-digit floats & NaN/Inf ⇒ Gorilla chosen, round-trip exact
  • overflow chunk-cut produces ≥2 independently-decodable chunks that recombine to the original (DELTA + DOD paths)
  • go vet / gofmt clean
  • bits/sample benchmark: INTCHUNK_BENCH_DIR=/path/to/per-series-json go test ./intchunk/ -run TestBenchmarkBitsPerSample -v (data lives outside the repo; test self-skips when unset)

NOTE: no integration and no deploy — follow-up PR6/PR7.

🤖 Generated with Claude Code

Standalone cold-tier raw-value chunk codec from the holistic-compression
design (§1.2-1.4 + §8). Per-series-per-block best-of-N picks the smallest
of three all-lossless candidates:

  GORILLA_XOR   (tag 0) lossless float64 via prometheus/tsdb/chunkenc XOR;
                always valid, the fallback for true high-precision floats.
  INT_FOR_DELTA (tag 1) float->int64 via decimal scale exp, FOR(base),
                delta, fixed-width bit-pack. For gauges.
  INT_FOR_DOD   (tag 2) same scale+FOR but delta-of-delta. For counters/
                monotonic and the timestamp column.

The load-bearing tryScaleToInt64 guard only emits an INT_* candidate when
float->int64->float round-trips BIT-EXACTLY at the chosen scale (decode
divides by the decimal-exact 10^e, never a rounded reciprocal); otherwise
only Gorilla is offered. Overflow chunk-cut: a residual exceeding the
integer width ends the chunk and re-bases (the cold drift->re-base).

Chunk header per §1.2: codec_tag u8, n_samples uvarint, timestamps as
t0 + delta-of-delta varints; INT tags add scale_exp i8, base zigzag-varint,
first_residual. Each chunk is self-contained and independently decodable.

Tests cover lossless round-trip (gauges/counters/high-precision floats/
constants/irregular ts/negatives), best-of-N picks the smallest valid
candidate, the exactness guard rejects 15+ sig-digit floats (=> Gorilla),
overflow produces multiple decodable chunks, and a randomized fuzz pass.
A bits/sample benchmark (set INTCHUNK_BENCH_DIR) confirms the verdict:
on the real Serf datasets INT beats Gorilla ~2.2x avg on fixed-decimal
(up to 3.6x) while best-of-N falls back to Gorilla on genuine float32-
derived series (Motor-temp, Air-pressure).

NOT wired into the agent encoder or merger; integration (agent encode +
decode-on-read StoreAPI + shared-ts) is the follow-up PR6/PR7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol zzylol changed the title feat(intchunk): cold INT best-of-N lossless value chunk codec (PR5) feat(intchunk): cold INT best-of-N lossless value chunk codec May 25, 2026
Add two INT sub-codecs that store the FOR delta / delta-of-delta residual
stream as per-residual zigzag varints instead of a single fixed bit width:

  INT_FOR_DELTA_VARINT (tag 3) FOR+delta, variable-length residuals
  INT_FOR_DOD_VARINT   (tag 4) FOR delta-of-delta, variable-length residuals

Both reuse the existing residual transform, header, and overflow chunk-cut;
only the trailing residual stream differs. Best-of-N now tries fixed-width
AND varint for both delta and delta-of-delta and keeps the smallest valid
candidate, so a block with near-uniform residuals takes the tight fixed
width while a skewed block (most deltas tiny, a few large) takes varints
and avoids paying the block's widest residual on every sample. The fixed
tags are unchanged; decode dispatches on the tag and each chunk stays
self-contained. All codecs remain bit-exact lossless and the decimal-
exactness guard still rejects non-exact INT (=> Gorilla).

Round-trip and best-of-N tests cover the new tags, including the varint
overflow cut and a skewed-residual block where varint beats fixed width
and best-of-N picks it. On the Serf datasets the per-block pick lifts the
fixed-decimal aggregate from ~2.2x to ~2.3x vs Gorilla (several series now
win with a varint codec) with no regression where fixed width is optimal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit d409d18 into main May 25, 2026
@zzylol
zzylol deleted the feat/cold-int-chunk-codec branch May 26, 2026 11:33
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