-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Engine/MemoryCache: Stage 1 improvements (RFC #2647) #2649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
- Add non-reentrant Cleanup() (SemaphoreSlim.Wait(0)) to prevent overlap - Introduce TryCleanupOnDemand(): cleans on demand (no background thread) - Triggered from DiscardPage (force when free > cap) - Triggered after Extend() requeues pages (signal + on next tick) - Lightweight tick every OPS_CLEANUP_STEP ops (default 256) - Eviction policy: idle + batch (DEFAULT_IDLE=60s, DEFAULT_BATCH=128) - Stamp freed timestamp (UTC ticks) when moving readable -> free - DiscardPage/Extend/Clear now set page.Timestamp - PageBuffer: atomic eviction guard (TryBeginEvict/MarkReusable) to avoid races - Clear(): requeue readable pages, return count, wake cleanup if over cap - Dispose(): block new triggers, wait any running cleanup, dispose lock - Conservative defaults: MaxFreePages=200, Idle=60s, Batch=128, Interval=30s - No public API changes Refs: litedb-org#1756, litedb-org#2619, RFC litedb-org#2647
|
@codex review |
|
Codex Review: Didn't find any major issues. You're on a roll. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting |
JKamsker
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few here - out of time - more later
| { | ||
| switch (profile) | ||
| { | ||
| case CacheProfile.Mobile: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like some more "Dynamic" way:
- CacheProfile becomes a struct or class
- CacheProfile has 3 static factory properties or readonly static fields if the nonstatic fields are readonly.
- CacheProfile can be configured with any of the 4 parameters mentioned (with checks)
|
|
||
| counter++; | ||
| // Check if we exceed free pages limit | ||
| if (_free.Count > _maxFreePages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_free.Count enumerates the whole collection. Try to use a cheaper volatile int and Interlocked. on it.
|
Just the one i could confirm in the timeframe i have. For the caching mechanism, something like this looks promising: Medium - Killing O(n): How Timing Wheels Expire 10 Million Keys Effortlessly in Golang. - putting cache items into timed buckets for a future worker to clean up |
|
Hi @JKamsker I haven't had time to review the GPT feedback regarding this change :( Just as a comment, I'd like to add that this version (which is possibly incomplete) is much better than the current version of LiteDb 5, which has a severe memory leak. My idea was to submit three versions: this would be the first, then the second with improvements, and the last with the final tuning, but as I said, it became impossible. I'll do my best to resume this fix, which I believe is very necessary for LiteDb. Thank you very much! |
Summary
This PR introduces the first round of improvements for the new in-memory cache in LiteDB 5.
Goal: make the cache more predictable, configurable, and robust under heavy concurrent load, while keeping all tests stable.
Key changes
Volatile on scalar tuning fields
_maxFreePages,_cleanupBatchSize,_extendsasvolatileto improve visibility across threads._idleBeforeEvict,_minCleanupInterval) remain asTimeSpan(structs cannot bevolatile).Safer on-demand cleanup triggers
NewPage()andGetWritablePage()to avoid interfering with segment extension andUniqueIDsequencing (fixes the failingCache_UniqueIDNumberingtest).GetReadablePage()(hot read path),DiscardPage()(when pages are freed),Clear()(manual cleanup),_maxFreePages(forced).SemaphoreSlim) with batched eviction and idle policy.Accurate comments & readability
Cleanup()docs to reference_cleanupBatchSizeand_idleBeforeEvict(instead of stale constants).Profiles groundwork
CacheProfile { Mobile, Desktop, Server }andApplyProfile(profile).// TODOmarker left in code).Motivation
LiteDB is often used in embedded scenarios with high concurrency and limited resources.
These changes make cache tuning safer and clearer without adding locking overhead or altering public APIs.
Impact
Related
Next steps
CacheProfileselection via engine parameter (Etapa 2).Checklist
dev-stagingNotes for reviewers