Skip to content

Commit 6e0e516

Browse files
refactor: address comments
Signed-off-by: Stepan Bagritsevich <[email protected]>
1 parent c123b8e commit 6e0e516

File tree

5 files changed

+54
-37
lines changed

5 files changed

+54
-37
lines changed

src/server/dfly_main.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -823,12 +823,7 @@ Usage: dragonfly [FLAGS]
823823
// export MIMALLOC_VERBOSE=1 to see the options before the override.
824824
mi_option_enable(mi_option_show_errors);
825825
mi_option_set(mi_option_max_warnings, 0);
826-
827826
mi_option_enable(mi_option_purge_decommits);
828-
DCHECK(mi_option_get(mi_option_reset_decommits) == 1);
829-
830-
mi_option_set(mi_option_purge_delay, 0);
831-
DCHECK(!mi_option_get(mi_option_reset_delay));
832827

833828
fb2::SetDefaultStackResource(&fb2::std_malloc_resource, kFiberDefaultStackSize);
834829

src/server/dragonfly_test.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ABSL_DECLARE_FLAG(float, mem_defrag_waste_threshold);
2626
ABSL_DECLARE_FLAG(uint32_t, mem_defrag_check_sec_interval);
2727
ABSL_DECLARE_FLAG(std::vector<std::string>, rename_command);
2828
ABSL_DECLARE_FLAG(bool, lua_resp2_legacy_float);
29+
ABSL_DECLARE_FLAG(bool, enable_heartbeat_eviction);
2930
ABSL_DECLARE_FLAG(double, eviction_memory_budget_threshold);
3031
ABSL_DECLARE_FLAG(std::vector<std::string>, command_alias);
3132

@@ -688,6 +689,8 @@ TEST_F(DefragDflyEngineTest, TestDefragOption) {
688689
absl::SetFlag(&FLAGS_mem_defrag_threshold, 0.0);
689690
absl::SetFlag(&FLAGS_mem_defrag_check_sec_interval, 0);
690691
absl::SetFlag(&FLAGS_mem_defrag_waste_threshold, 0.1);
692+
// We need to disable heartbeat eviction because it enfluences the defragmentation
693+
absl::SetFlag(&FLAGS_enable_heartbeat_eviction, false);
691694

692695
// Fill data into dragonfly and then check if we have
693696
// any location in memory to defrag. See issue #448 for details about this.

src/server/engine_shard.cc

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ ABSL_FLAG(double, eviction_memory_budget_threshold, 0.1,
6767
"Eviction starts when the free memory (including RSS memory) drops below "
6868
"eviction_memory_budget_threshold * max_memory_limit.");
6969

70-
ABSL_FLAG(uint64_t, force_decommit_threshold, 8_MB,
71-
"The threshold of memory to force decommit when memory is under pressure.");
72-
7370
ABSL_DECLARE_FLAG(uint32_t, max_eviction_per_heartbeat);
7471

7572
namespace dfly {
@@ -325,41 +322,55 @@ bool EngineShard::DefragTaskState::CheckRequired() {
325322
return false;
326323
}
327324

328-
std::optional<ShardMemUsage> shard_mem_usage;
329-
330-
if (GetFlag(FLAGS_enable_heartbeat_eviction)) {
331-
shard_mem_usage = ReadShardMemUsage(GetFlag(FLAGS_mem_defrag_page_utilization_threshold));
332-
const static double eviction_waste_threshold = 0.05;
333-
if (shard_mem_usage->wasted_mem >
334-
(uint64_t(shard_mem_usage->commited * eviction_waste_threshold))) {
335-
VLOG(1) << "memory issue found for memory " << shard_mem_usage.value();
336-
return true;
337-
}
338-
}
339-
340-
const std::size_t global_threshold = max_memory_limit * GetFlag(FLAGS_mem_defrag_threshold);
325+
/*
326+
If the eviction is enabled, we want to run the defrag task more frequently and more aggressively.
327+
For global threshold rss we use the rss memory minus the eviction budget threshold and minus 3%
328+
- For example if rss_deny_oom_ratio is 0.8 and eviction_memory_budget_threshold is 0.1,
329+
we will start eviction when rss memory is above 0.8 - 0.1 = 0.7. And defragmentation
330+
should still working if used rss memory is above 0.7 - 0.03 = 0.67.
331+
For defrag interval we use the EvictionTaskState::kMemDefragCheckSecInterval
332+
For waste threshold we use the EvictionTaskState::kEvictionWasteThreshold
333+
*/
334+
const bool is_eviction_enabled = GetFlag(FLAGS_enable_heartbeat_eviction);
335+
336+
const double mem_defrag_threshold_flag = GetFlag(FLAGS_mem_defrag_threshold);
337+
const double defrag_threshold =
338+
!is_eviction_enabled ? mem_defrag_threshold_flag
339+
: std::min(mem_defrag_threshold_flag,
340+
ServerState::tlocal()->rss_oom_deny_ratio -
341+
GetFlag(FLAGS_eviction_memory_budget_threshold) -
342+
EvictionTaskState::kDefragRssMemoryDelta);
343+
344+
const std::size_t global_threshold = max_memory_limit * defrag_threshold;
341345
if (global_threshold > rss_mem_current.load(memory_order_relaxed)) {
342346
return false;
343347
}
344348

345349
const auto now = time(nullptr);
346350
const auto seconds_from_prev_check = now - last_check_time;
347-
const auto mem_defrag_interval = GetFlag(FLAGS_mem_defrag_check_sec_interval);
351+
352+
const uint32_t check_sec_interval_flag = GetFlag(FLAGS_mem_defrag_check_sec_interval);
353+
const auto mem_defrag_interval =
354+
!is_eviction_enabled
355+
? check_sec_interval_flag
356+
: std::min(check_sec_interval_flag, EvictionTaskState::kDefragCheckSecInterval);
348357

349358
if (seconds_from_prev_check < mem_defrag_interval) {
350359
return false;
351360
}
352-
last_check_time = now;
353361

354-
if (!shard_mem_usage) {
355-
shard_mem_usage = ReadShardMemUsage(GetFlag(FLAGS_mem_defrag_page_utilization_threshold));
356-
}
362+
last_check_time = now;
357363

358-
DCHECK(shard_mem_usage.has_value());
364+
ShardMemUsage shard_mem_usage =
365+
ReadShardMemUsage(GetFlag(FLAGS_mem_defrag_page_utilization_threshold));
359366

360-
const double waste_threshold = GetFlag(FLAGS_mem_defrag_waste_threshold);
361-
if (shard_mem_usage->wasted_mem > (uint64_t(shard_mem_usage->commited * waste_threshold))) {
362-
VLOG(1) << "memory issue found for memory " << shard_mem_usage.value();
367+
const float waste_threshold_flag = GetFlag(FLAGS_mem_defrag_waste_threshold);
368+
const double waste_threshold =
369+
!is_eviction_enabled
370+
? waste_threshold_flag
371+
: std::min(waste_threshold_flag, EvictionTaskState::kDefragWasteThreshold);
372+
if (shard_mem_usage.wasted_mem > (uint64_t(shard_mem_usage.commited * waste_threshold))) {
373+
VLOG(1) << "memory issue found for memory " << shard_mem_usage;
363374
return true;
364375
}
365376

@@ -858,7 +869,7 @@ size_t EngineShard::CalculateEvictionBytes() {
858869
size_t goal_bytes = CalculateHowManyBytesToEvictOnShard(max_memory_limit, global_used_memory,
859870
shard_memory_budget_threshold);
860871

861-
LOG_IF_EVERY_N(INFO, goal_bytes > 0, 50)
872+
VLOG_IF_EVERY_N(1, goal_bytes > 0, 50)
862873
<< "Memory goal bytes: " << goal_bytes << ", used memory: " << global_used_memory
863874
<< ", memory limit: " << max_memory_limit;
864875

@@ -889,7 +900,7 @@ size_t EngineShard::CalculateEvictionBytes() {
889900
max_rss_memory, global_used_rss_memory - deleted_bytes_before_rss_update * shards_count,
890901
shard_rss_memory_budget_threshold);
891902

892-
LOG_IF_EVERY_N(INFO, rss_goal_bytes > 0, 50)
903+
VLOG_IF_EVERY_N(1, rss_goal_bytes > 0, 50)
893904
<< "Rss memory goal bytes: " << rss_goal_bytes
894905
<< ", rss used memory: " << global_used_rss_memory
895906
<< ", rss memory limit: " << max_rss_memory

src/server/engine_shard.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ class EngineShard {
220220
};
221221

222222
struct EvictionTaskState {
223+
/* This constant are used to control the defragmentation task when eviction is enabled.
224+
The task is run periodically to check whether we need to do memory defragmentation.
225+
When eviction is enabled, we want to make defragment task run more frequently
226+
and also we want to make waste threshold lower to allow more aggressive defragmentation. */
227+
static constexpr uint32_t kDefragCheckSecInterval = 2;
228+
static constexpr float kDefragWasteThreshold = 0.05;
229+
static constexpr double kDefragRssMemoryDelta = 0.03;
230+
223231
size_t deleted_bytes_before_rss_update = 0;
224232
size_t global_rss_memory_at_prev_eviction = 0;
225233
};

tests/dragonfly/memory_test.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ async def test_cache_eviction_with_rss_deny_oom_simple_case(
256256
break
257257

258258
# Wait for some time
259-
await asyncio.sleep(2)
259+
await asyncio.sleep(3)
260260

261261
memory_arena = await async_client.execute_command("MEMORY", "ARENA")
262262
fragmentation_waste = extract_fragmentation_waste(memory_arena)
@@ -319,10 +319,10 @@ async def test_cache_eviction_with_rss_deny_oom_two_waves(
319319
rss_eviction_threshold = max_memory * (rss_oom_deny_ratio - eviction_memory_budget_threshold)
320320

321321
# first wave fills 85% of max memory
322-
# second wave fills 20% of max memory
322+
# second wave fills 17% of max memory
323323
data_fill_size = [
324324
int((rss_oom_deny_ratio + 0.05) * max_memory),
325-
int((1 - rss_oom_deny_ratio) * max_memory),
325+
int((1 - rss_oom_deny_ratio - 0.03) * max_memory),
326326
]
327327

328328
val_size = 1024 * 5 # 5 kb
@@ -372,7 +372,7 @@ async def test_cache_eviction_with_rss_deny_oom_two_waves(
372372
break
373373

374374
# Wait for some time
375-
await asyncio.sleep(2)
375+
await asyncio.sleep(3)
376376

377377
memory_arena = await async_client.execute_command("MEMORY", "ARENA")
378378
fragmentation_waste = extract_fragmentation_waste(memory_arena)
@@ -387,7 +387,7 @@ async def test_cache_eviction_with_rss_deny_oom_two_waves(
387387
rss_oom_deny_ratio - eviction_memory_budget_threshold - 0.05
388388
), "We should not evict all items."
389389
assert memory_info["used_memory"] < max_memory * (
390-
rss_oom_deny_ratio - eviction_memory_budget_threshold + 0.05
390+
rss_oom_deny_ratio - eviction_memory_budget_threshold + 0.08
391391
), "Used memory should be smaller than threshold."
392392
assert memory_info["used_memory_rss"] > max_memory * (
393393
rss_oom_deny_ratio - eviction_memory_budget_threshold - 0.05

0 commit comments

Comments
 (0)