MOD-15579 Lazy initialization of the shared SVS thread pool#971
Open
dor-forer wants to merge 3 commits into
Open
MOD-15579 Lazy initialization of the shared SVS thread pool#971dor-forer wants to merge 3 commits into
dor-forer wants to merge 3 commits into
Conversation
🛡️ Jit Security Scan Results✅ No security findings were detected in this PR
Security scan by Jit
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dor-forer-MOD-15578-track-svs-thpool-memory #971 +/- ##
============================================================================
Coverage 96.97% 96.97%
============================================================================
Files 130 130
Lines 7829 7845 +16
============================================================================
+ Hits 7592 7608 +16
Misses 237 237 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
31c0e0a to
0adca87
Compare
6b4b160 to
8fe69ac
Compare
0adca87 to
9d082f0
Compare
8fe69ac to
760524d
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 760524d. Configure here.
760524d to
75228a3
Compare
* `VecSimSVSThreadPoolImpl::resetForTest()`: assert `pending_jobs_ == 0` before clearing state so misuse fails loudly instead of corrupting the deferred-protocol bookkeeping. * `SVSTest.NumThreadsParamIgnored`: restore the singleton via `resetForTest()` (clears `has_attached_index_` + slots) instead of leaving `has_attached_index_` set for subsequent tests. * `SVSTest.ThreadPoolLazyInit`: tighten post-`VecSimIndex_New` checks from `EXPECT_*` to `ASSERT_*` so a regression in the lazy-spawn contract halts the test on the first failure instead of cascading. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75228a3 to
f278e8d
Compare
Open
4 tasks
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.

Make initialization of the shared SVS thread pool lazy: OS worker threads are spawned only when the first SVS index is created, not when
VecSim_UpdateThreadPoolSizeis called. This eliminates the cost of pre-allocated SVS workers in deployments that configure RediSearch workers but never create an SVS index (today, every Redis withWORKERS=Nconfigured spawnsN-1SVS worker threads at module init regardless of whether SVS is ever used).The change extends the existing deferred-resize protocol to cover a second "safe point".
VecSimSVSThreadPoolImpl::resize()now defers application in two cases:onIndexAttached()(lazy thread spawn).pending_jobs_ > 0) → recorded; applied whenendScheduledJob()drops the counter to 0 (existing behaviour).resize_locked().The two deferral cases share
deferred_size_and never overlap (no jobs can be in flight before the first index attaches). One new gate field,has_attached_index_, distinguishes the two states. Set on the firstonIndexAttached()call from the per-indexVecSimSVSThreadPoolctor.A test-only
resetForTest()hook (underBUILD_TESTS) restores the singleton to a clean baseline by releasing the slots vector capacity and clearing the new gate; intended for unit tests that need to observe lazy semantics in a process where prior tests may have already attached indexes.VecSim_UpdateThreadPoolSizecontinues to set the write mode (InPlace/Async) eagerly — only the SVS pool sizing is now deferred. The C API surface is unchanged.RediSearch integration impact: none required —
VecSim_UpdateThreadPoolSize(N)is still the single entry point for both module init andCONFIG SET search-workers M. Pre-index calls now just record the size; post-index calls behave exactly as before.Main objects this PR modified
VecSimSVSThreadPoolImpl::resize()— now lazy until first index attaches.VecSimSVSThreadPoolImpl::onIndexAttached()— new entry point called from per-indexVecSimSVSThreadPoolctor; flipshas_attached_index_and applies any deferred size.VecSimSVSThreadPoolImpl::has_attached_index_— new member field gating spawn vs. defer.VecSimSVSThreadPoolImpl::resetForTest()— newBUILD_TESTS-only hook.VecSim_UpdateThreadPoolSize()— comment updated; behaviour now lazy via the newresize()semantics.Tests
SVSTest.ThreadPoolLazyInit(new) — verifiesVecSim_UpdateThreadPoolSizedoes not allocate worker threads before any SVS index exists, and that the first SVS index creation triggers the deferred spawn at the previously requested size.SVSThreadPoolTest.UpdateThreadPoolSizeModeTransitions— rewritten to validate the lazy → eager transition (size stays at 1 until an index attaches; subsequent transitions are immediate).SVSThreadPoolTestfixture —SetUp()callsonIndexAttached()so the existing pool-isolation tests retain eagerresize()semantics.SVSTest.NumThreadsParamIgnored— callsonIndexAttached()upfront for the same reason.SVSTest.debugInfoGlobalMemoryEqualsSharedSVSThreadPoolMemory—ASSERT_GTon global memory moved to afterCreateNewIndex(the lazy spawn fires there).Mark if applicable
Supersedes #969 — ownership transferred to @dor-forer.
Note
Medium Risk
Changes when OS threads and pool memory appear relative to module init and
CONFIG SET search-workers, but the public C API is unchanged and shrink-while-jobs-in-flight deferral is preserved; risk is mainly operational surprise if something assumed threads existed before any SVS index.Overview
Lazy initialization defers spawning OS worker threads for the shared SVS thread pool until the first SVS index attaches.
VecSim_UpdateThreadPoolSizestill sets write mode immediately and still callsresize(), but before any index exists that call only records the target size indeferred_size_instead of creating threads—so Redis deployments withsearch-workersconfigured but no SVS index no longer pay for unused SVS workers at module init.The existing deferred-shrink path (shrink while
pending_jobs_ > 0) is unchanged insideresize_locked(). A new gate,has_attached_index_, splits behavior: pre-attach resizes are record-only; post-attach resizes go throughresize_locked()as before. The firstVecSimSVSThreadPoolconstruction callsonIndexAttached(), which flips the gate and applies any recorded size.A
BUILD_TESTS-onlyresetForTest()clears slots,deferred_size_, andhas_attached_index_so unit tests can observe lazy semantics on the process-wide singleton. Tests were added/updated (ThreadPoolLazyInit, lazy→eagerUpdateThreadPoolSizetransitions, fixtureonIndexAttachedfor isolated pool tests).Reviewed by Cursor Bugbot for commit f278e8d. Bugbot is set up for automated code reviews on this repo. Configure here.