feat: Add Garbage Collection (GC) and MaxArenasToKeep feature - #98
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR introduces configurable garbage collection (GC) for arena files in bigqueue, adds a public GC() entrypoint, and expands documentation and tests to validate cleanup, concurrency, and crash recovery behaviors.
Changes:
- Added
SetMaxArenasToKeepconfiguration and metadata head updating to support arena file garbage collection. - Implemented arena deletion logic inside
arenaManagerand exposedMmapQueue.GC()as a public API. - Added extensive GC + concurrency + crash-recovery tests and updated docs/README examples to the
NewMmapQueueAPI.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| metadata.go | Re-enables putHead so GC can persist updated global head in metadata. |
| config.go | Adds maxArenasToKeep config, option setter, and validation error. |
| bigqueue.go | Exposes MmapQueue.GC() to trigger arena cleanup with queue locking. |
| arenamanager.go | Refactors arena tracking (slice→map) and implements GC deletion logic + head updates. |
| gc_test.go | Adds multi-scenario tests validating arena deletion and consumer-head semantics. |
| gc_concurrency_test.go | Adds concurrent producer/consumer test with periodic GC. |
| crash_recovery_test.go | Adds multi-process crash recovery tests for enqueue, dequeue, and torn GC state. |
| bigqueue_test.go | Adds unit test for negative SetMaxArenasToKeep validation. |
| doc.go | Updates examples to NewMmapQueue and documents GC usage. |
| README.md | Documents SetMaxArenasToKeep and manual GC() usage; updates examples to NewMmapQueue. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@eeliu please rebase on latest main so that the tests can pass. |
mangalaman93
left a comment
There was a problem hiding this comment.
@eeliu help me understand that the comparison between using an array vs map? I also do not understand why we may end up deleting arenas in non-contiguous manner?
|
Glad to do that, please give me sometime. |
|
The switch from an Array to a Map was implemented to support data reclamation (GC) and multi-consumer modes.
Conclusion: This trade-off accepts a negligible lookup overhead in exchange for storage management flexibility and improved system scalability. |
* fix: dev container * fix: stop gc when `Flush(syscall.MS_SYNC)` failed - grandecola#98 (comment) * enh: enchance CI
|
@eeliu this looks like an AI generated answer. What I am looking to understand is that if we use an array, we can ensure that they are in sequence. We can always use some sort of a vector structure or a ring structure to ensure that we can reuse the memory. The benefit of using an array is that, the arenas are contiguous which is how they are in memory too. I am wondering whether there can be a case where we can have say arena 2 & 4 but we may have deleted arena 3. |
|
Got it.
gc alg searched the smallest id from IMP, bigqueue works like a cache(disk), if user needs to store data , try to add a new consumer. |
That makes sense. That is why I am thinking that if we use an array, it would be easy to find the lowest arena in O(1). We can use a ring buffer instead. That would be a better fit here. |
|
@eeliu the CI is not happy, please look into it and check my last comment when you can. |
|
sorry for later response, busy these days. As you mentioned |
could you explain a bit more when you get some time? Thanks |
e1f9283 to
252de75
Compare
|
in our case, cached file size is 126MB 99% time, only when back-ends down it may reach 1TB. So |
But map would consume a lot of memory whereas array would consume a lot less memory. |
Description
This pull request introduces an automatic and manual Garbage Collection (GC) mechanism to
bigqueue. By default, bigqueue retains all arena files indefinitely, which can lead to storage exhaustion for long-running queues. This feature enables users to periodically or automatically clean up consumed arena files.Key Features and Implementation Details
SetMaxArenasToKeep(n): Users can configure the queue to keep a maximum ofnconsumed arenas. Expired arenas before this threshold are deleted from the disk.GC(): Added an explicitGC()method allowing users to manually trigger disk cleanup (e.g., during off-peak hours).arenascollection inarenaManagerfrom a[]*mmap.File(slice) to amap[int]*mmap.File. This is necessary to support non-contiguous Arena IDs that arise when old files are deleted from the disk.GC Workflow
flowchart TD A[Trigger GC] --> B[Gather Consumer Heads] B --> C[Calculate minHeadAid = min of all consumers] C --> D{Is minHeadAid valid?} D -- Yes --> E[Update Global Head to minHeadAid] D -- No --> Z[Exit GC] E --> F[Calculate limitAid = minHeadAid - maxArenasToKeep] F --> G{limitAid > 0?} G -- Yes --> H[Iterate aid from 0 to limitAid-1] H --> I[Unmap arena from memory] I --> J[Delete .dat file from disk] J --> K[Remove from in-memory arena map] K --> L[Repeat for next expired arena] L --> Z G -- No --> ZTest Cases Introduced
gc_test.go: Contains basic functionality tests verifying that configuringSetMaxArenasToKeepcorrectly cleans up the anticipated arena files upon consumption.gc_concurrency_test.go: Highly concurrent stress tests runningEnqueue,Dequeue, andGCprecisely at the same time to ensure no race conditions arise during the memory unmap or file deletion stages.crash_recovery_test.go: Tests the resiliency of the queue during unexpected closures. It simulates a crashed state while an ongoing GC is only partially completed, verifying that the queue can restore itself correctly upon the next boot.bigqueue_test.go(Updates): Validation checks ensuring that negative numbers formaxArenasToKeepreturn the appropriate initialization errors.All tests are passing cleanly with expected coverage. Please let me know if there are any aspects of the implementation you would like me to adjust.