Avatar for the dualeai user
dualeai
seek
BlogDocsChangelog

Performance History

Latest Results

Merge branch 'develop'
main
21 days ago
Cut folder-corpus cold ingest Five small folder_indexer.go changes: 1. ensureFolderCorpusFresh: reuse the pre-lock shardsExist result ('hasShards || shardsExist(...)') so a concurrent indexer's late shards are still picked up but the warm gate skips the redundant Glob. 2. scanFolderRootEntriesParallel: jobs channel sized to len(entries) instead of 'workers'. The feeder drains in one non-blocking pass; the workers-sized buffer was serializing dispatch. 3. scanFolderRootEntriesParallel: pre-compute the merged 'selected' slice capacity from each piece's selectedCandidates total. Drops the capacity-doubling reallocations on large trees. 4. fingerprintRootEntry: short-circuit non-regular files via DirEntry.Type() before calling entry.Info(). Type() reads the cached readdir d_type with no syscall; only regular files have Type()==0. Saves one Lstat per non-regular root entry. 5. walkDirectory inner loop: skip the .git metadata-dir check before building the path string instead of after. README field-benchmark table refreshed from a clean 'cicd/bench-field.sh --no-linux' run on the post-change tree. Microbench numbers reproducible via 'make test-bench'. Tests in folder_indexer_fastpath_test.go cover each of the five changes at the right layer: - TestEnsureFolderCorpusFresh_WarmCallExercisesPreLockGate: pins the cache fix by asserting the on-disk state file is populated between the cold and warm calls (the gate's precondition). - TestFolderCorpusStateParallel_HighFanout_NoStallNoDrop: drives folderCorpusStateParallel directly with 200 subdirs so the parallel dispatcher (not the serial walker) runs; asserts every entry's file reached the selected set. - TestFolderCorpusStateParallel_IdempotentSelectedAndStateHash: proves merge-loop determinism through two parallel-scan runs. - TestFingerprintRootEntry_NonRegular_SkipsEntryInfo: 12 sub-cases covering every non-zero DirEntry.Type() bit (symlink, named-pipe, socket, device, char-device, irregular, plus setuid/setgid/sticky/ temporary/append/exclusive markers). Asserts Info() count stays zero via a spy fake. - TestFingerprintRootEntry_RegularFile_CallsInfo: positive case; Info() count must be 1. - TestWalkDirectory_GitContentNotInStateHash: mutates .git/sentinel and asserts hash stability. - TestWalkDirectory_GitPresenceAffectsBoundaryMarker: confirms the boundary-marker contribution still fires when .git appears. - TestEnsureFolderCorpusFresh_ColdThenWarm_SearchableBoth: end-to-end smoke through the full indexing path. Heavy tests (ones invoking Zoekt + ctags) gate on testing.Short and requireTools so 'go test -short' stays fast. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
develop
21 days ago
Add read-semaphore + windowed shard indexing; fix deadlock + perf PROBLEM Folder corpora exceeding `maxInFlightBytes` (600 MiB) wedged indexing in a three-way deadlock: workers blocked on `readSemaphore.Acquire`, producers blocked on channel send, consumer blocked waiting to close the channel — `builder.Finish()` never ran so the aggregate `Release` never fired. Reproduced live at PID 51141 with `seek "lol" ~/Downloads ~/Development/git/.../monorepo ~/Documents` (4.1 GiB folder hung at 530 MB RSS, 0% CPU). FIX — windowed shard rotation `indexDocuments` now rotates a `shardWindow` builder every `indexWindowBytes` (300 MiB default, half of `maxInFlightBytes`). Each window releases its accumulated weight after `builder.Finish()` returns, bounding peak in-flight bytes to `indexWindowBytes + 2 × maxIndexedDocumentBytes` (compile-time invariant in `caps.go`). Five-layer architecture: LAYER A: indexDocuments — windowed rotation (indexer.go) LAYER B: readUncommittedCandidates — bounded drain returning errUncommittedPayloadTooLarge (indexer.go) LAYER C: indexFolderDocumentsDelta — content-bytes guard returning errFolderDeltaPayloadTooLarge (folder_indexer.go) LAYER D/E: indexUncommitted + indexFolderDocuments catch the sentinels via errors.Is and fall back to LAYER A's windowed full rebuild. PERFORMANCE Beyond the deadlock fix, multiple optimizations land: 1. Pre-flight lstat-sum short-circuit in readUncommittedCandidates and changedFolderDocumentsFromManifest: O(N) loop summing candidate.size returns the window sentinel BEFORE any read syscall. Bench shows 24x speedup vs the slow drain path, 0 allocs vs 268 KiB on the overflow path (BenchmarkReadUncommittedCandidates_PreFlight). 2. Streaming JSON encoder for writeFolderManifest + writeUncommittedManifest: json.NewEncoder + bufio.Writer replaces json.Marshal + os.WriteFile. Cuts peak transient allocation from ~2x payload to bufio working set (~32 KiB). On 100k entries: 22 MB peak vs 44 MB pre-fix (BenchmarkWriteFolderManifest/100k). 3. Parallel per-shard search in executeParsedSearchScoped: fan-out across runtime.NumCPU goroutines bounded by a semaphore channel. Single-shard fast path preserved. Wall time becomes max-of-shards instead of sum-of-shards; 5-10x speedup at 100+ shards (BenchmarkShardSearch_NShards). 4. acquireSearchLock stale-shard fallback: when LOCK_SH is contended AND shards exist in indexDir, returns nil with slog.Warn instead of polling 60s. Mirrors acquireLock's equivalent fallback. Bench: 117 us fast path (BenchmarkAcquireSearchLock_StaleFallback). 5. FD ceiling startup warn: warnLowFileDescriptorLimit logs a hint when soft RLIMIT_NOFILE < 4096 (multi-corpus rotation can hold 3 corpora x ~420 shards = ~1260 fds during search). 6. Per-plan context.WithCancel in main.go wrapped in func + defer cancelPlan: panic-safe cleanup ensures no cross-plan semaphore leak via the process-global readSemaphore. 7. Stale-shard fallback in acquireLock now logs slog.Warn instead of silent: hung indexer was previously masked as graceful degradation forever. 8. GC sweeps orphan .folder-manifest-v1.tmp + .uncommitted-manifest-v1.tmp files older than 1 hour. INSTRUMENTATION shardWindowFinishes / shardWindowMetaRewrites atomic.Int64 counters surface the rotation cost in benchmarks (BenchmarkFolderCorpus_ColdIndex_LargeRotation reports windows/op + metaRewrites/op). Quadratic IsDelta=true meta rewrite cost is now CI-visible: 15 rewrites/op for 6 windows matches Sum(N=0..5)=15 formula exactly. folderDeltaPreflightTrips / folderDeltaContentTrips atomic.Int64 counters distinguish which guard branch fired so tests can verify the pre-flight optimization specifically (not just the post-read content-bytes guard). TESTS 18 new test files covering: pressure (4 MiB swap budget + 12 MiB payload), cancellation with goleak, multi-corpus sequential drain, property/fuzz over file-size distributions, cross-window early-beacon survival, pre-flight short-circuit isolation, acquireSearchLock both branches, soak (4 GiB sparse for 5 min, gated behind //go:build soak + SEEK_SOAK=1). Helpers: planSynthCorpus, writeRandomFolder, writeSparseFile, goroutineLeakGuard, withReadSemLock, swapReadSemaphoreForTest (also swaps indexWindowBytes proportionally), swapIndexWindowBytesForTest, waitUntilSemaphoreBelow, mustHoldTestReadSemMu (TryLock panic guard against future t.Parallel misuse). 5 new benchmarks isolating each perf optimization with b.ReportMetric for shard count, window count, allocation peak, and meta-rewrite cost. Validates every claim above. BREAKING CHANGE streamFiles signature now requires context.Context. acquireSearchLock signature now requires the indexDir string. fileContent embeds a weight field that the consumer must Release exactly once: per shardWindow.finish() for indexDocuments, per call for indexDeltaDocuments (see read_semaphore.go and indexer.go::fileContent docstrings). All in-tree callers updated. VERIFICATION go test -race -timeout=600s: PASS (373s) golangci-lint run: 0 issues Repro: seek "lol" \$HOME/Downloads ... completes instead of wedging. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
develop
22 days ago
Merge branch 'develop'
main
23 days ago
Merge branch 'develop'
main
24 days ago

Latest Branches

CodSpeed Performance Gauge
N/A
Add CodSpeed continuous performance benchmarks#5
3 months ago
a8a8937
codspeed-wizard-1774529268605
© 2026 CodSpeed Technology
Home Terms Privacy Docs