diff --git a/db/column_family.cc b/db/column_family.cc index 819d12bc1..2d4c980e7 100644 --- a/db/column_family.cc +++ b/db/column_family.cc @@ -904,7 +904,7 @@ int GetL0ThresholdSpeedupCompaction(int level0_file_num_compaction_trigger, namespace { const int kMemtablePenalty = 5; const int kNumPendingSteps = 100; -const double kGoalMbs = 5242880.0; +const double kGoalMbs = 3 * 1048576.0; } // namespace double ColumnFamilyData::TEST_CalculateWriteDelayDivider( @@ -1040,8 +1040,7 @@ ColumnFamilyData::CalculateWriteDelayDividerAndMaybeUpdateWriteStallCause( // This is calculated and set when the L0L1 compaction ends in // CompactionJob::Install. // Use this rate for the first extra slowdown files and then heavily delay the - // rest of the files. In any case, delay at least 2 - // * trigger. + // rest of the files. In any case, delay at least 2 * trigger. // slowdown 12 ; stop 30; - start at 22 // slowdown 12 ; stop 50; - start at 24 @@ -1054,33 +1053,51 @@ ColumnFamilyData::CalculateWriteDelayDividerAndMaybeUpdateWriteStallCause( auto gap = stop - slowdown; if ((gap > (slowdown + 2 * trigger))) { file_to_start_delay = slowdown + 2 * trigger; - } else if (slowdown + (2 * trigger) < stop) { - file_to_start_delay = slowdown + trigger; } else { file_to_start_delay = slowdown; } - // The goal is to reach kGoalMbs 3 steps before stop condition so that we - // never reach it. The formula to decide the delay percentage is: kGoalMbs = - // start_rate * (delay_percent ^ num_steps) where: kGoalMbs = 5 , start_rate - // is the l0_compaction_speed num_steps = num_L0_steps - 3. + // Initial delay (2/3 of the steps) is done linearly to avoid a big delay + // early on and the rest is exponential. For the exponential part, the goal is + // to reach kGoalMbs 1 step before stop condition so that we never reach it. + // The formula to decide the delay percentage is: kGoalMbs = start_rate * + // (delay_percent ^ num_delay_steps) where: start_rate is the rate at the last + // linear step, and num_delay_steps is num_steps_till_stop - 1. double l0_divider = 1; + const int kGoalMbStep = 1; const auto extra_l0_ssts = vstorage->l0_delay_trigger_count() - file_to_start_delay; if (extra_l0_ssts > 0) { - const auto num_L0_steps = stop - file_to_start_delay; - assert(num_L0_steps > 0); - double num_steps = num_L0_steps > 6 ? num_L0_steps - 1 : num_L0_steps; - auto base = (kGoalMbs / 5) / l0_base_compaction_speed(); - // in cases where l0_base_compaction_speed() is lower than our goal Mbs - if (base > 1) { - base = 0.95; + const auto num_steps_till_stop = stop - file_to_start_delay; + assert(num_steps_till_stop > 0); + double num_delay_steps = num_steps_till_stop - kGoalMbStep; + const int linear_steps = num_delay_steps * (2.0 / 3); + const auto initial_linear_rate = l0_base_compaction_speed(); + const int mb_per_linear_step = + (initial_linear_rate - kGoalMbs) / num_delay_steps; + if (extra_l0_ssts <= linear_steps) { + double l0_files_rate = + initial_linear_rate - (extra_l0_ssts * mb_per_linear_step); + assert(l0_files_rate > 0); + l0_divider = initial_linear_rate / l0_files_rate; + } else { + // calculate exponential delay from last linear step. + auto last_linear_step_mbs = + initial_linear_rate - (linear_steps * mb_per_linear_step); + auto base = kGoalMbs / last_linear_step_mbs; + // in cases where last_linear_step_mbs is lower than our goal Mbs + if (base > 1) { + base = 0.95; + } + auto num_exp_steps = num_delay_steps - linear_steps; + double delay_percent = std::pow(base, 1.0 / num_exp_steps); + assert(delay_percent > 0 && delay_percent < 1); + // since extra_l0_ssts == num_steps_till_stop then we're in a stop + // condition. + assert(extra_l0_ssts < num_steps_till_stop); + auto l0_rate = last_linear_step_mbs * + std::pow(delay_percent, (extra_l0_ssts - linear_steps)); + l0_divider = initial_linear_rate / l0_rate; } - double delay_percent = std::pow(base, 1.0 / num_steps); - assert(delay_percent > 0 && delay_percent < 1); - // since extra_l0_ssts == num_L0_steps then we're in a stop condition. - assert(extra_l0_ssts < num_L0_steps); - - l0_divider = 1 / (std::pow(delay_percent, extra_l0_ssts)); } if (l0_divider > biggest_divider) {