Defrag changes#7876
Conversation
|
augment review |
🤖 Augment PR SummarySummary: Refines tiered-storage defragmentation to reduce memory pressure and make cleanup self-healing. Changes:
Technical Notes: The defrag scan runs as part of the offloading heartbeat and aims to keep overhead low when the small-bin table is already compacted. 🤖 Was this summary useful? React with 👍 or 👎 |
|
|
||
| uint64_t cycles = 0; | ||
| do { | ||
| if (UploadBudget() < 0) |
There was a problem hiding this comment.
src/server/tiered_storage.cc:735: RunDefragScan() only breaks when UploadBudget() < 0, so it still runs when the budget is exactly 0. That differs from NotifyDelete()'s UploadBudget() > 0 gate and may enqueue defrags when there's no upload headroom.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| if (UploadBudget() < 0) | ||
| break; | ||
|
|
||
| if (op_manager_->stats_.pending_defrags > kMaxPendingDefrags) |
There was a problem hiding this comment.
| auto cb = [this, &hits](size_t offset) { | ||
| tiering::DiskSegment segment{offset, tiering::kPageSize}; | ||
| if (!op_manager_->HasReadPending(kFragmentedBin, segment)) { | ||
| op_manager_->EnqueueForDefrag({offset, tiering::kPageSize}); |
There was a problem hiding this comment.
src/server/tiered_storage.cc:724: The scan callback enqueues via EnqueueForDefrag() without checking pending_defrags/UploadBudget(), so a single TraverseFragmented() step can schedule many defrags before the outer loop re-checks limits.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| stats_.stashed_entries_cnt += list.size(); | ||
| stashed_bins_[segment.offset] = {uint8_t(list.size()), bytes}; | ||
|
|
||
| stashed_bins_.Insert(segment.offset, StashInfo{uint8_t(list.size()), bytes}); |
There was a problem hiding this comment.
src/server/tiering/small_bins.cc:106: DashTable::Insert() returns false on duplicate keys; ignoring the return can silently keep an old StashInfo while still incrementing stashed_entries_cnt. If the same segment.offset is ever reported twice (e.g. reuse/race), stats and fragmentation tracking can drift.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
PR Summary by QodoAdaptive background defrag scan and DashTable tracking for small bins
AI Description
Diagram
High-Level Assessment
Files changed (11)
|
|
|
||
| // Dynamic behaviour: nothing is fragmented anymore, so further heartbeat scans are cheap no-ops. | ||
| size_t defrags_now = GetMetrics().tiered_stats.total_defrags; | ||
| util::ThisFiber::SleepFor(100ms); // ~10 heartbeats at hz=100 |
There was a problem hiding this comment.
src/server/tiered_storage_test.cc:512: The fixed SleepFor(100ms) assumes ~10 heartbeats at hz=100, which can be timing-sensitive in CI (different FLAGS_hz or slower scheduling) and make this test intermittently fail. Consider making the final “no further defrags” assertion purely condition-based rather than time-based.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Code Review by Qodo
🟡 Remediation Recommended 1.
|
|
|
||
| // Notify delete. Return true if the filled segment needs to be marked as free. | ||
| virtual bool NotifyDelete(DiskSegment segment) = 0; | ||
| // If was_read is set, the item was just read and can still be reached with a read |
There was a problem hiding this comment.
I do not understand the comment. What does it mean?
There was a problem hiding this comment.
It means NotiftyDelete can either be called after a read or just so arbitrarily when a value is deleted - in the first case we have access to the value that was deleted
|
|
||
| // Notify delete. Return true if the filled segment needs to be marked as free. | ||
| virtual bool NotifyDelete(DiskSegment segment) = 0; | ||
| // Under was_read this function was called after a read completion as the follow-up delete |
There was a problem hiding this comment.
I saw this style several times so I want to comment here about naming and contracts.
was_read and the comment above explains how you got here (the caller context) and not what it does for the function. The contract is not clear. While the logic is sound I think a better style, imho - to describe the variables (and their meaning) in terms of a contract without bringing the caller context into it if possible. For example,
// Notify delete. Return true if the filled segment needs to be marked as free.
// page_in_memory is true when the delete follows a completed read, so the page's data is
// still in the pending-reads cache and defrag can reuse it without an extra disk read.
bool NotifyDelete(DiskSegment segment, bool page_in_memory) = 0;
if you are changing the name, please sync it with every NotifyDelete declaration/implementation
|
|
||
| stats_.stashed_entries_cnt += list.size(); | ||
| stashed_bins_[segment.offset] = {uint8_t(list.size()), bytes}; | ||
| stashed_bins_.InsertNew(segment.offset, StashInfo{uint8_t(list.size()), bytes}); |
There was a problem hiding this comment.
how are you sure the key is unique?
where in the flow before we check for it?
| @@ -676,7 +669,7 @@ void TieredStorage::RunOffloading(DbIndex dbid) { | |||
| const auto start_cycles = base::CycleClock::Now(); | |||
|
|
|||
| // Takes up a small fixed amount of time and is best done before offloading (to be picked up) | |||
There was a problem hiding this comment.
nit: fixed -> bounded, but also revisit the comment if it still applies as is.
| return u == v; | ||
| } | ||
|
|
||
| static uint64_t HashFn(uint64_t v) { |
There was a problem hiding this comment.
actually that was an overkill
There was a problem hiding this comment.
no, no overkill - dividing by kPageSize breaks the dashtable as it requires high bits to be set as well
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
Signed-off-by: Vladislav Oleshko <vlad@dragonflydb.io>
Uh oh!
There was an error while loading. Please reload this page.