Repository navigation
Conversation
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 5, 2026 16:19
9c001bd to
b7c7396
Compare
Base automatically changed from
tamirms/events-windowed-matches
to
tamirms/events-pack-byte-limit
October 5, 2026 16:19
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 8, 2026 08:18
b7c7396 to
9dd7c16
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 8, 2026 08:34
9dd7c16 to
d6850e4
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
3 times, most recently
from
October 9, 2026 14:28
54bd67e to
2f48a12
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
2 times, most recently
from
October 15, 2026 19:15
486acc2 to
f07e219
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 19, 2026 13:00
f07e219 to
f3ef45d
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
5 times, most recently
from
October 21, 2026 11:16
ec8b39b to
bfa3418
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 21, 2026 14:43
420e116 to
5f84830
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 21, 2026 17:05
5f84830 to
be8a0bb
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 21, 2026 17:15
be8a0bb to
06cf851
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
3 times, most recently
from
October 23, 2026 05:27
67cd29e to
bfb8832
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
4 times, most recently
from
October 24, 2026 02:49
5b10819 to
d3e7b89
Compare
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
October 28, 2026 08:05
d3e7b89 to
67dde93
Compare
…slabs A popular term's bitmap is read whole for every page that touches it: on pubnet chunk 6410 the fifteen most popular terms are 250 KiB to 1.08 MiB each, so a popular page reads about 9 MB of index to answer from a few slabs of it. And index.pack's 128-entry records make its tail follow the term count, which no fixed first read covers on big chunks, so every open there pays a second round trip. A term whose serialized bitmap is over 64 KiB is now stored as one entry per slab of the chunk, zero-length where it has no events, and LookupKeys reads only the slabs the window reaches and reports their span as covered. The app data names the split terms after the chunk's slab count, one 8-byte row of slot and fingerprint each, and the blob has an exact length. The stamp keeps its version, since nothing has shipped: index packs written before this change have to be rebuilt. Records close at 16 KiB with no entry limit, so the tail follows the file size, and Open's first read is max(64 KiB, 4 bytes per 16 KiB of file), rounded up to 4 KiB. Every stage of a query after the first now asks for at most 16 slabs rather than the whole rest of the window. A split term is read only for a stage's slabs, at most one container per slab, so a query holds at most 128 KiB of each split term at once whatever the chunk's density, under 2 MiB for queryEvents' 15-term budget. Measured on gp3 with a cold page cache, against the code before this change: five popular terms over four slabs took 1.8 ms p50 instead of 11.9 ms on a pubnet chunk folded to seven times its density, and 12 ms instead of 118 ms with eight query streams each reading its own copy. A rare term took 3.0 ms instead of 5.3 ms on sac-6000, whose tail now fits one read. A read of a split term's whole chunk rebuilds the term from its slab entries, about 0.5 ms more CPU per term on the folded chunk than decoding one whole bitmap. A page that never fills, on the folded chunk with its 16 most popular terms paired so that they never occur together, holds 2.2 MB at a time rather than 37 MB, and 200 such pages take 0.61 GB of resident memory rather than 13.9 GB. Alone and warm it takes 96 ms instead of 82 ms; under load its throughput and total CPU are the same. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JCzMKKrK3NstGKvaxsHhL2
When a query has a split term, each stage's answer covers only that stage, so Matches asks for every term again at the next stage, and the cold reader read and decoded every non-split term each time. The reader now keeps each non-split entry it decodes and hands later stages the same bitmap. A cold reader serves one request, so what it keeps is bounded by that request's terms. Callers already treat lookup results as read-only, so the two tests that pinned a fresh bitmap per lookup on one reader go. One test now pins that two readers share nothing, and another that a later stage gets the whole term the first stage decoded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wwsd8qTEGeSb7poFEYcgg9
tamirms
force-pushed
the
tamirms/events-split-terms
branch
from
November 4, 2026 10:07
67dde93 to
1297fdc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A popular term's bitmap is read whole for every page that touches it: on
pubnet chunk 6410 the fifteen most popular terms are 250 KiB to 1.08 MiB
each, so a popular page reads about 9 MB of index to answer from a few
slabs of it. And index.pack's 128-entry records make its tail follow the
term count, which no fixed first read covers on big chunks, so every open
there pays a second round trip.
A term whose serialized bitmap is over 64 KiB is now stored as one entry
per slab of the chunk, zero-length where it has no events, and LookupKeys
reads only the slabs the window reaches and reports their span as
covered. The app data names the split terms after the chunk's slab
count, one 8-byte row of slot and fingerprint each, and the blob has an
exact length. The stamp keeps its version, since nothing has shipped:
index packs written before this change have to be rebuilt. Records close at 16 KiB with no
entry limit, so the tail follows the file size, and Open's first read is
max(64 KiB, 4 bytes per 16 KiB of file), rounded up to 4 KiB.
Every stage of a query after the first now asks for at most 16 slabs
rather than the whole rest of the window. A split term is read only for
a stage's slabs, at most one container per slab, so a query holds at
most 128 KiB of each split term at once whatever the chunk's density,
under 2 MiB for queryEvents' 15-term budget.
When a query has a split term, each stage's answer covers only that
stage's slabs, so the next stage asks for every term again. The cold
reader keeps each whole term it decodes and hands later stages of the
same request that bitmap instead of reading and decoding it again. A
cold reader serves one request, so what it keeps is bounded by that
request's terms, and callers already treat lookup results as
read-only. One request's staged lookups of one split term and 14 whole
terms just under 64 KiB, with the files in the page cache, took 1.0 ms
and allocated 3 MiB instead of 3.3 ms and 15 MiB on 156 slabs (pubnet
density, 11 stages), and 4.4 ms and 10 MiB instead of 33 ms and
115 MiB on 916 slabs (six times that density, 58 stages).
Measured on gp3 with a cold page cache, against the code before this
change: five popular terms over four slabs took 1.8 ms p50 instead of
11.9 ms on a pubnet chunk folded to seven times its density, and 12 ms
instead of 118 ms with eight query streams each reading its own copy. A
rare term took 3.0 ms instead of 5.3 ms on sac-6000, whose tail now fits
one read. A read of a split term's whole chunk rebuilds the term from
its slab entries, about 0.5 ms more CPU per term on the folded chunk
than decoding one whole bitmap.
A page that never fills, on the folded chunk with its 16 most popular
terms paired so that they never occur together, holds 2.2 MB at a time
rather than 37 MB, and 200 such pages take 0.61 GB of resident memory
rather than 13.9 GB. Alone and warm it takes 96 ms instead of 82 ms;
under load its throughput and total CPU are the same.
🤖 Generated with Claude Code