Skip to content

Add GarnetRecordDisposer with per-record dispose on page eviction#1689

Merged
badrishc merged 2 commits into
devfrom
badrishc/garnet-record-disposer
Apr 10, 2026
Merged

Add GarnetRecordDisposer with per-record dispose on page eviction#1689
badrishc merged 2 commits into
devfrom
badrishc/garnet-record-disposer

Conversation

@badrishc

Copy link
Copy Markdown
Collaborator

Add IRecordDisposer.DisposeRecord(ref LogRecord, DisposeReason) callback that allows applications to clean up external resources when records are disposed during page eviction.

Add DisposeRecordsInRangeForEviction to ObjectAllocatorImpl, which iterates records on evicted pages (skipping page header, null, and closed records) and calls storeFunctions.DisposeRecord for each, giving the application access to the full record while data is still intact. Wired into AllocatorBase.OnPagesClosedWorker after the existing eviction observer and before FreePage, gated by DisposeOnPageEviction.

Note: ObjectAllocatorImpl.DisposeRecord (the existing internal method for delete, compaction, CAS failure, etc.) is unchanged. The new storeFunctions.DisposeRecord is only called from the eviction range scan.

Add GarnetRecordDisposer replacing DefaultRecordDisposer. Sets DisposeOnPageEviction=false and DisposeRecord as a no-op for now. Consuming features (e.g. RangeIndex) will set DisposeOnPageEviction=true and add record type handlers.

Changes:

  • IRecordDisposer: add DisposeRecord(ref LogRecord, DisposeReason) with default no-op
  • IStoreFunctions, StoreFunctions: add DisposeRecord delegation
  • ObjectAllocatorImpl: add DisposeRecordsInRangeForEviction
  • AllocatorBase.OnPagesClosedWorker: call DisposeRecordsInRangeForEviction when DisposeOnPageEviction is true
  • IAllocator, ObjectAllocator, SpanByteAllocator, TsavoriteLogAllocator: add DisposeRecordsInRangeForEviction
  • GarnetRecordDisposer: new struct replacing DefaultRecordDisposer
  • GlobalUsings.cs: DefaultRecordDisposer -> GarnetRecordDisposer
  • GarnetServer.cs: pass GarnetRecordDisposer to StoreFunctions.Create

Copilot AI review requested due to automatic review settings April 10, 2026 00:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new per-record disposal hook that runs during page eviction, enabling applications to clean up external resources while the evicted record is still intact in memory.

Changes:

  • Extend Tsavorite record disposer APIs with DisposeRecord(ref LogRecord, DisposeReason) and plumb it through IStoreFunctions/StoreFunctions.
  • Add DisposeRecordsInRangeForEviction(startAddress, endAddress) and invoke it from AllocatorBase.OnPagesClosedWorker when DisposeOnPageEviction is enabled.
  • Introduce GarnetRecordDisposer and update Garnet server/tests/global usings to use it.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
test/Garnet.test/GarnetObjectTests.cs Update store creation to pass GarnetRecordDisposer into StoreFunctions.Create.
libs/storage/Tsavorite/cs/src/core/Index/StoreFunctions/StoreFunctions.cs Add DisposeRecord delegation to the configured IRecordDisposer.
libs/storage/Tsavorite/cs/src/core/Index/StoreFunctions/IStoreFunctions.cs Add DisposeRecord(ref LogRecord, DisposeReason) to store-functions interface.
libs/storage/Tsavorite/cs/src/core/Index/StoreFunctions/IRecordDisposer.cs Add default no-op DisposeRecord callback for per-record cleanup.
libs/storage/Tsavorite/cs/src/core/Allocator/TsavoriteLogAllocator.cs Add stub DisposeRecordsInRangeForEviction implementation.
libs/storage/Tsavorite/cs/src/core/Allocator/SpanByteAllocator.cs Add (currently empty) DisposeRecordsInRangeForEviction implementation.
libs/storage/Tsavorite/cs/src/core/Allocator/ObjectAllocatorImpl.cs Implement eviction-range iteration that calls storeFunctions.DisposeRecord per record.
libs/storage/Tsavorite/cs/src/core/Allocator/ObjectAllocator.cs Expose DisposeRecordsInRangeForEviction via allocator wrapper.
libs/storage/Tsavorite/cs/src/core/Allocator/IAllocator.cs Extend allocator interface with DisposeRecordsInRangeForEviction.
libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs Invoke eviction disposal scan in OnPagesClosedWorker when enabled.
libs/server/Storage/Functions/GarnetRecordDisposer.cs Add new Garnet-specific record disposer (currently no-op / disabled for eviction).
libs/host/GarnetServer.cs Pass GarnetRecordDisposer into store-functions creation.
libs/GlobalUsings.cs Switch Garnet store function/allocator aliases from DefaultRecordDisposer to GarnetRecordDisposer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread libs/storage/Tsavorite/cs/src/core/Allocator/IAllocator.cs Outdated
Comment thread libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs
Comment thread libs/storage/Tsavorite/cs/src/core/Allocator/SpanByteAllocator.cs
Add IRecordDisposer.DisposeRecord(ref LogRecord, DisposeReason) callback
that allows applications to clean up external resources when records are
disposed during page eviction.

Add DisposeRecordsInRangeForEviction to ObjectAllocatorImpl, which
iterates records on evicted pages (skipping page header, null, and closed
records) and calls storeFunctions.DisposeRecord for each, giving the
application access to the full record while data is still intact. Wired
into AllocatorBase.OnPagesClosedWorker after the existing eviction
observer and before FreePage, gated by DisposeOnPageEviction.

Note: ObjectAllocatorImpl.DisposeRecord (the existing internal method for
delete, compaction, CAS failure, etc.) is unchanged. The new
storeFunctions.DisposeRecord is only called from the eviction range scan.

Add GarnetRecordDisposer replacing DefaultRecordDisposer. Sets
DisposeOnPageEviction=false and DisposeRecord as a no-op for now.
Consuming features (e.g. RangeIndex) will set DisposeOnPageEviction=true
and add record type handlers.

Changes:
- IRecordDisposer: add DisposeRecord(ref LogRecord, DisposeReason)
  with default no-op
- IStoreFunctions, StoreFunctions: add DisposeRecord delegation
- ObjectAllocatorImpl: add DisposeRecordsInRangeForEviction
- AllocatorBase.OnPagesClosedWorker: call DisposeRecordsInRangeForEviction
  when DisposeOnPageEviction is true
- IAllocator, ObjectAllocator, SpanByteAllocator, TsavoriteLogAllocator:
  add DisposeRecordsInRangeForEviction
- GarnetRecordDisposer: new struct replacing DefaultRecordDisposer
- GlobalUsings.cs: DefaultRecordDisposer -> GarnetRecordDisposer
- GarnetServer.cs: pass GarnetRecordDisposer to StoreFunctions.Create

Co-authored-by: Copilot <[email protected]>
@badrishc badrishc force-pushed the badrishc/garnet-record-disposer branch from cae25bb to cd646e7 Compare April 10, 2026 01:12
@badrishc badrishc merged commit 4520781 into dev Apr 10, 2026
55 of 59 checks passed
@badrishc badrishc deleted the badrishc/garnet-record-disposer branch April 10, 2026 02:24
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 9, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants