Refactor of ActiveDefrag to reduce latencies#13814
Merged
sundb merged 21 commits intoredis:unstablefrom Feb 19, 2025
Merged
Conversation
Co-authored-by: ShooterIT <wangyuancode@163.com>
Collaborator
Author
|
becnmark Latency by percentile distribution this PR: |
At the same time, Add the upper limit for perodic process
ShooterIT
approved these changes
Feb 19, 2025
Co-authored-by: ShooterIT <wangyuancode@163.com>
sundb
added a commit
that referenced
this pull request
Feb 23, 2025
1) Fix a bug that passing an incorrect endtime to module. This bug was found by @ShooterIT. After #13814, all endtime will be monotonic time, and we should no longer convert it to ustime relative. Add assertions to prevent endtime from being much larger thatn the current time. 2) Fix a race in test `Reduce defrag CPU usage when module data can't be defragged` --------- Co-authored-by: ShooterIT <wangyuancode@163.com>
fcostaoliveira
pushed a commit
to filipecosta90/redis
that referenced
this pull request
Feb 24, 2025
1) Fix a bug that passing an incorrect endtime to module. This bug was found by @ShooterIT. After redis#13814, all endtime will be monotonic time, and we should no longer convert it to ustime relative. Add assertions to prevent endtime from being much larger thatn the current time. 2) Fix a race in test `Reduce defrag CPU usage when module data can't be defragged` --------- Co-authored-by: ShooterIT <wangyuancode@163.com>
sundb
added a commit
that referenced
this pull request
May 18, 2025
In PR #13229, we introduced the ebucket for HFE. Before this PR, when updating eitems stored in ebuckets, the lack of incremental fragmentation support for non-kvstore data structures (until PR #13814) meant that we had to reverse lookup the position of the eitem in the ebucket and then perform the update. This approach was inefficient as it often required frequent traversals of the segment list to locate and update the item. To address this issue, in this PR, This PR implements incremental fragmentation for hash dict ebuckets and server.hexpires. By incrementally defrag the ebuckets, we also perform defragmentation for the associated items, eliminates the need for frequent traversals of the segment list for defragging the eitem. --------- Co-authored-by: Moti Cohen <moticless@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
sundb
added a commit
that referenced
this pull request
May 27, 2025
… timer to run twice as fast (#14081) This bug was introduced in [#13814](#13814), and was found by @guybe7. It incorrectly moved the update of `server.cronloops` from `whileBlockedCron()` to `activeDefragTimeProc()`, causing the cron-based timers to effectively run twice as fast when active defrag is enabled. As a result, memory statistics are not updated during blocked operations. The repair parts from #13995, because it needs to be backport, so use a separate pr repair it.
YaacovHazan
pushed a commit
to YaacovHazan/redis
that referenced
this pull request
May 27, 2025
… timer to run twice as fast (redis#14081) This bug was introduced in [redis#13814](redis#13814), and was found by @guybe7. It incorrectly moved the update of `server.cronloops` from `whileBlockedCron()` to `activeDefragTimeProc()`, causing the cron-based timers to effectively run twice as fast when active defrag is enabled. As a result, memory statistics are not updated during blocked operations. The repair parts from redis#13995, because it needs to be backport, so use a separate pr repair it.
YaacovHazan
pushed a commit
that referenced
this pull request
May 27, 2025
… timer to run twice as fast (#14081) This bug was introduced in [#13814](#13814), and was found by @guybe7. It incorrectly moved the update of `server.cronloops` from `whileBlockedCron()` to `activeDefragTimeProc()`, causing the cron-based timers to effectively run twice as fast when active defrag is enabled. As a result, memory statistics are not updated during blocked operations. The repair parts from #13995, because it needs to be backport, so use a separate pr repair it.
sundb
added a commit
that referenced
this pull request
Jun 5, 2025
… expires stage (#14092) This bug was introduced by #13814 When defragmenting `db->expires`, if the process exits early and `db->expires` was modified in the meantime (e.g., FLUSHDB), we need to check whether the previously defragmented expires is still the same as the current one when resuming. If they differ, we should abort the current defragmentation of expires. However, in #13814, I made a mistake by using `db->keys` and `db->expires`, as expires will never be defragged.
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.
This PR is based on: valkey-io/valkey#1242
Issue/Problems
Duty Cycle: Active Defrag has configuration values which determine the intended percentage of CPU to be used based on a gradient of the fragmentation percentage. However, Active Defrag performs its work on the 100ms serverCron timer. It then computes a duty cycle and performs a single long cycle. For example, if the intended CPU is computed to be 10%, Active Defrag will perform 10ms of work on this 100ms timer cron.
Maintainability: The current Active Defrag code is difficult to read & maintain. Refactoring of the high level control mechanisms and functions will allow us to more seamlessly adapt to new defragmentation needs. Specific examples include:
Description of the feature
Primarily, this feature will split activeDefragCycle into 2 functions.
Once the functions are split, there is more control over the latency created by the defrag process. A new constant(DEFRAG_CYCLE_US) will be used to determine the running time for the defrag timer proc. The value for this will be 500us (one-half of the current minimum time). Then the timer will be adjusted to achieve the desired CPU. As an example, 5% of CPU will run the defrag process for 500us every 10ms. This is much better than running for 5ms every 100ms.
The timer function will also adjust to compensate for starvation. If a slow command delays the timer, the process will run proportionately longer to ensure that the configured CPU is achieved. Given the presence of slow commands, the proportional extra time is insignificant to latency. This also addresses the overload case. At 100% CPU, if the event loop slows, defrag will run proportionately longer to achieve the configured CPU utilization.
Optionally, in low CPU situations, there would be little impact in utilizing more than the configured CPU. We could optionally allow the timer to pop more often (even with a 0ms delay) and the (tail) latency impact would not change.
Addressing maintainability:
Different from Valkey
Signed-off-by: Jim Brunner brunnerj@amazon.com
Signed-off-by: Madelyn Olson madelyneolson@gmail.com
Co-authored-by: Madelyn Olson madelyneolson@gmail.com