Jim Brunner 397201c48f
Refactor of ActiveDefrag to reduce latencies (#1242)
Refer to:  https://github.com/valkey-io/valkey/issues/1141

This update refactors the defrag code to:
* Make the overall code more readable and maintainable
* Reduce latencies incurred during defrag processing

With this update, the defrag cycle time is reduced to 500us, with more
frequent cycles. This results in much more predictable latencies, with a
dramatic reduction in tail latencies.

(See https://github.com/valkey-io/valkey/issues/1141 for more complete
details.)

This update is focused mostly on the high-level processing, and does NOT
address lower level functions which aren't currently timebound (e.g.
`activeDefragSdsDict()`, and `moduleDefragGlobals()`). These are out of
scope for this update and left for a future update.

I fixed `kvstoreDictLUTDefrag` because it was using up to 7ms on a CME
single shard. See original github issue for performance details.

---------

Signed-off-by: Jim Brunner <brunnerj@amazon.com>
Signed-off-by: Madelyn Olson <madelyneolson@gmail.com>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
2024-12-03 08:42:29 -08:00

46 lines
1.6 KiB
Tcl

set testmodule [file normalize tests/modules/defragtest.so]
start_server {tags {"modules"} overrides {{save ""}}} {
r module load $testmodule 10000
r config set active-defrag-ignore-bytes 1
r config set active-defrag-threshold-lower 0
r config set active-defrag-cycle-min 99
# try to enable active defrag, it will fail if the server was compiled without it
catch {r config set activedefrag yes} e
if {[r config get activedefrag] eq "activedefrag yes"} {
test {Module defrag: simple key defrag works} {
r frag.create key1 1 1000 0
after 2000
set info [r info defragtest_stats]
assert {[getInfoProperty $info defragtest_datatype_attempts] > 0}
assert_equal 0 [getInfoProperty $info defragtest_datatype_resumes]
}
test {Module defrag: late defrag with cursor works} {
r flushdb
r frag.resetstats
# key can only be defragged in no less than 10 iterations
# due to maxstep
r frag.create key2 10000 100 1000
after 2000
set info [r info defragtest_stats]
assert {[getInfoProperty $info defragtest_datatype_resumes] > 10}
assert_equal 0 [getInfoProperty $info defragtest_datatype_wrong_cursor]
}
test {Module defrag: global defrag works} {
r flushdb
r frag.resetstats
after 2000
set info [r info defragtest_stats]
assert {[getInfoProperty $info defragtest_global_attempts] > 0}
}
}
}