Skip to content

perf(server): default the inverted index to MaxPendingPostings=Recommended (2M) - #111

Merged
oc-engteam merged 1 commit into
mainfrom
perf/server-default-maxpending
Jul 10, 2026
Merged

perf(server): default the inverted index to MaxPendingPostings=Recommended (2M)#111
oc-engteam merged 1 commit into
mainfrom
perf/server-default-maxpending

Conversation

@oc-engteam

Copy link
Copy Markdown
Collaborator

What

The server built core/invertedindex with a zero-value Options{}, so MaxPendingPostings was 0 = unbounded — the in-memory pending-write buffer grew until the periodic flush drained it, giving a noisy ~1.1–1.5 GiB peak build RSS at scale. This wires the production construction to pass the measured-good bound RecommendedMaxPendingPostings (2,000,000).

Why (measured)

iibench on the linux corpus (94,559 docs / 41.4M postings, 4× interleaved avg, prod default vs 2M):

unbounded (today) 2M (this PR)
peak build RSS ~1.28 GiB (noisy 1.1–1.5) ~0.66 GiB (tight 0.6–0.7), −48%
peak Go heap ~1.15 GiB ~0.54 GiB (−53%)
build wall-time ~56 s ~62 s (+11%)
alloc traffic / GC 6.9 GiB / ~36 9.1 GiB / ~166
search / hits ~2063 µs / 2,414,505 ~2140 µs / 2,414,505 (identical)

Peak build RSS is roughly halved and made predictable (unbounded is race-dependent and noisy), for a ~+11% build cost and more flush/GC churn — a deliberate memory-over-build-speed default for the possibly-small-RAM deployment target.

Scope

Consumer opt-in only. The core/invertedindex zero-value contract (MaxPendingPostings 0 = unbounded) is unchanged, so the published core module and its other consumers are unaffected — only the server sets the bound. git diff touches only internal/server/.

A newInvertedIndex constructor seam lets a light unit test capture the Options the production invertedindexInit closure passes and assert the bound (a genuine red→green guard against a silent revert to unbounded — verified: dropping the bound makes the test fail with MaxPendingPostings = 0). No on-disk change; search/hits unaffected.

Verification

Built via the full SDD flow (spec, 3 review rounds to a clean round, then workflow-driven TDD). Local gates green (go1.24.2 + go.work): build / vet / gofmt / internal/server tests; and the root go-cov gate: zero CRITICAL, total 94.0% (internal/server 95.3%).

🤖 Generated with Claude Code

…ended (2M)

The server constructed core/invertedindex with a zero-value Options{}, so
MaxPendingPostings was 0 = UNBOUNDED and the in-memory pending-write buffer grew
until the periodic flush drained it — a noisy ~1.1-1.5 GiB peak build RSS at
linux scale.

Wire the production construction (invertedindexInit) to pass the measured-good
bound RecommendedMaxPendingPostings (2,000,000). Measured with iibench on the
linux corpus (94,559 docs / 41.4M postings, 4x avg): peak build RSS ~1.28 GiB ->
~0.66 GiB (-48%) and, importantly, PREDICTABLE (unbounded is noisy) — for a
measured ~+11% build time and more flush/GC churn. A deliberate memory-over-
build-speed default for the possibly-small-RAM deployment target.

Scope: consumer opt-in only. The core/invertedindex library zero-value contract
(MaxPendingPostings 0 = unbounded) is unchanged, so the published module and its
other consumers are unaffected; only the server sets the bound.

Adds a newInvertedIndex constructor seam so a light unit test captures the Options
the production closure passes and asserts the bound (a regression guard against a
silent revert to unbounded). No on-disk change; search/hits unaffected.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@oc-engteam
oc-engteam merged commit bc895b5 into main Jul 10, 2026
4 checks passed
@oc-engteam
oc-engteam deleted the perf/server-default-maxpending branch July 10, 2026 04:16
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.

2 participants