Skip to content

nyc-311: global-dict street columns ~54MB larger than vortex-jni (dict codes not bitpacked?) #303

Description

@dfa1

Summary

After #299 (and PR #302, FSST child cascade), vortex-java is now 30 MB smaller than the vortex-jni reference on nyc-311 (1731 vs 1762 MB). The largest remaining cluster where java is bigger is three high-cardinality street columns — pure upside to close.

Evidence — per-column bytes (java re-encode vs vortex-jni, nyc-311, chunk 65536)

Column distinct jni MB java MB delta jni encoding
Cross Street 1 ~27,634 31.8 50.1 +18.3 fastlanes.bitpacked, vortex.fsst
Cross Street 2 ~23,674 31.8 50.1 +18.3 fastlanes.bitpacked, vortex.fsst
Street Name ~20,082 29.8 47.1 +17.3 fastlanes.bitpacked, vortex.fsst

~54 MB combined. All three are now admitted to the global dictionary (the #299 type-aware Utf8 cap of 32768 works — they round-trip as vortex.dict layouts), and their values pool is FSST-compressed (#299 Finding 2). But jni's layout is ~36% smaller.

Hypothesis

Two likely, non-exclusive causes — both worth checking before fixing:

  1. Dict codes stored raw, not bitpacked. The global-dict codes are per-chunk U16 arrays (18.49M rows × 2 B ≈ 37 MB just for codes). jni tags these columns fastlanes.bitpacked. A dict of ~27k values needs only 15 bits, and finer per-chunk cardinality needs fewer — so bitpacking (or FoR) the codes could recover several MB per column. This is the same class of issue PR Cascade FSST offset/length children (#299) #302 fixed for the FSST offset/length children: a child left as raw vortex.primitive instead of cascaded. Check whether writeGlobalDictUtf8Column's code segments actually bitpack (they route through writeSegment → cascade; a nullable-masked wrapper may be blocking the inner bitpack).

  2. Global vs per-chunk dict tradeoff. jni appears to use a per-chunk dict (dict encoding, not a global dict layout) with its finer 32k–64k chunking, so each chunk's code width tracks that chunk's (smaller) local cardinality rather than the global 27k. At this cardinality the per-chunk approach may simply win.

Where

Context

Follow-up to #299 / PR #302. Measured on the hydrated Raincloud nyc-311 corpus (18.49M rows × 42 cols). Not started — analysis only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions