From f53277f82be8efb3c381202d19c03233bec0d3fb Mon Sep 17 00:00:00 2001 From: Qian Ge Date: Mon, 10 Aug 2026 23:11:30 -0700 Subject: [PATCH] Internal change. PiperOrigin-RevId: 962582327 --- tcmalloc/experiment_config.h | 2 ++ tcmalloc/huge_page_subrelease.h | 13 ++++++++++++- tcmalloc/huge_page_subrelease_test.cc | 9 ++++++++- tcmalloc/parameters.cc | 12 ++++++++++-- tcmalloc/testing/get_stats_test.cc | 21 +++++++++++++++------ tcmalloc/variants.bzl | 6 ++++++ 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/tcmalloc/experiment_config.h b/tcmalloc/experiment_config.h index 657d1d405..44840586b 100644 --- a/tcmalloc/experiment_config.h +++ b/tcmalloc/experiment_config.h @@ -23,6 +23,7 @@ namespace tcmalloc { enum class Experiment : int { // clang-format off // go/keep-sorted start + TCMALLOC_DEMAND_CYCLE_120S, // TODO: b/540987155 - Complete experiment. TCMALLOC_HUGE_REGION_ADAPTIVE_RELEASE, // TODO: b/535197873 - Complete experiment. TCMALLOC_PER_CPU_CACHE_SIZE_1MB, // TODO: b/514747820 - Complete experiment. TCMALLOC_PGHO_EXPERIMENT, // TODO: b/460486507 - Complete experiment. @@ -53,6 +54,7 @@ struct ExperimentConfig { // clang-format off inline constexpr ExperimentConfig experiments[] = { // go/keep-sorted start + {Experiment::TCMALLOC_DEMAND_CYCLE_120S, "TCMALLOC_DEMAND_CYCLE_120S"}, {Experiment::TCMALLOC_HUGE_REGION_ADAPTIVE_RELEASE, "TCMALLOC_HUGE_REGION_ADAPTIVE_RELEASE"}, {Experiment::TCMALLOC_PER_CPU_CACHE_SIZE_1MB, "TCMALLOC_PER_CPU_CACHE_SIZE_1MB"}, {Experiment::TCMALLOC_PGHO_EXPERIMENT, "TCMALLOC_PGHO_EXPERIMENT"}, diff --git a/tcmalloc/huge_page_subrelease.h b/tcmalloc/huge_page_subrelease.h index 36e7a36d3..048545203 100644 --- a/tcmalloc/huge_page_subrelease.h +++ b/tcmalloc/huge_page_subrelease.h @@ -24,6 +24,7 @@ #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "tcmalloc/common.h" +#include "tcmalloc/experiment.h" #include "tcmalloc/huge_pages.h" #include "tcmalloc/internal/clock.h" #include "tcmalloc/internal/config.h" @@ -332,7 +333,17 @@ class SubreleaseStatsTracker { // spikes. The demand is capped to the peak observed in the history window. Length GetRecentDemand(absl::Duration short_interval, absl::Duration long_interval) { - return GetRecentDemand(short_interval, long_interval, demand_cap_interval_); + if (IsExperimentActive(Experiment::TCMALLOC_DEMAND_CYCLE_120S)) { + // As the interval value can be updated online, we have to load the + // demand_cap_interval here rather than in the constructor. + return GetRecentDemand(short_interval, long_interval, + long_interval == absl::ZeroDuration() + ? short_interval + : long_interval); + } else { + return GetRecentDemand(short_interval, long_interval, + demand_cap_interval_); + } } // Calculates demand requirements for the skip subrelease: we do not diff --git a/tcmalloc/huge_page_subrelease_test.cc b/tcmalloc/huge_page_subrelease_test.cc index 4bae04e39..d51a80567 100644 --- a/tcmalloc/huge_page_subrelease_test.cc +++ b/tcmalloc/huge_page_subrelease_test.cc @@ -238,7 +238,14 @@ TEST_F(StatsTrackerTest, ComputeRecentDemand) { GenerateDemandPoint(Length(10), Length(7)); Length short_long_peak_pages5 = tracker_.GetRecentDemand(absl::ZeroDuration(), absl::Minutes(51)); - EXPECT_EQ(short_long_peak_pages5, Length(10)); + if (IsExperimentActive(Experiment::TCMALLOC_DEMAND_CYCLE_120S)) { + // When the experiment is on, we use the peak within the long_interval to + // cap the demand. The peak in 51 min is 150 and the calculated demand is + // 100. + EXPECT_EQ(short_long_peak_pages5, Length(100)); + } else { + EXPECT_EQ(short_long_peak_pages5, Length(10)); + } } TEST_F(StatsTrackerTest, ComputeRecentDemandAndCappedToPeak) { diff --git a/tcmalloc/parameters.cc b/tcmalloc/parameters.cc index bc5145e64..cea8d806b 100644 --- a/tcmalloc/parameters.cc +++ b/tcmalloc/parameters.cc @@ -109,7 +109,11 @@ static std::atomic& skip_subrelease_short_interval_ns() { #if defined(TCMALLOC_INTERNAL_SMALL_BUT_SLOW) interval = absl::ZeroDuration(); #else - interval = absl::Seconds(60); + if (IsExperimentActive(Experiment::TCMALLOC_DEMAND_CYCLE_120S)) { + interval = absl::Seconds(10); + } else { + interval = absl::Seconds(60); + } #endif absl::base_internal::LowLevelCallOnce(&flag, [&]() { @@ -127,7 +131,11 @@ static std::atomic& skip_subrelease_long_interval_ns() { #if defined(TCMALLOC_INTERNAL_SMALL_BUT_SLOW) interval = absl::ZeroDuration(); #else - interval = absl::Seconds(300); + if (IsExperimentActive(Experiment::TCMALLOC_DEMAND_CYCLE_120S)) { + interval = absl::Seconds(120); + } else { + interval = absl::Seconds(300); + } #endif absl::base_internal::LowLevelCallOnce(&flag, [&]() { diff --git a/tcmalloc/testing/get_stats_test.cc b/tcmalloc/testing/get_stats_test.cc index 26b4a7805..50bf3177e 100644 --- a/tcmalloc/testing/get_stats_test.cc +++ b/tcmalloc/testing/get_stats_test.cc @@ -106,12 +106,21 @@ TEST_F(GetStatsTest, Pbtxt) { EXPECT_THAT(buf, HasSubstr("tcmalloc_skip_subrelease_short_interval_ns: 0")); EXPECT_THAT(buf, HasSubstr("tcmalloc_skip_subrelease_long_interval_ns: 0")); #else - EXPECT_THAT( - buf, - HasSubstr("tcmalloc_skip_subrelease_short_interval_ns: 60000000000")); - EXPECT_THAT( - buf, - HasSubstr("tcmalloc_skip_subrelease_long_interval_ns: 300000000000")); + if (IsExperimentActive(Experiment::TCMALLOC_DEMAND_CYCLE_120S)) { + EXPECT_THAT( + buf, + HasSubstr("tcmalloc_skip_subrelease_short_interval_ns: 10000000000")); + EXPECT_THAT( + buf, + HasSubstr("tcmalloc_skip_subrelease_long_interval_ns: 120000000000")); + } else { + EXPECT_THAT( + buf, + HasSubstr("tcmalloc_skip_subrelease_short_interval_ns: 60000000000")); + EXPECT_THAT( + buf, + HasSubstr("tcmalloc_skip_subrelease_long_interval_ns: 300000000000")); + } #endif EXPECT_THAT(buf, HasSubstr("tcmalloc_release_partial_alloc_pages: true")); diff --git a/tcmalloc/variants.bzl b/tcmalloc/variants.bzl index c4c3ba04b..54a1f2879 100644 --- a/tcmalloc/variants.bzl +++ b/tcmalloc/variants.bzl @@ -289,6 +289,12 @@ test_variants = [ "deps": ["//tcmalloc:common_8k_pages"], "env": {"BORG_EXPERIMENTS": "TCMALLOC_SONIC_MADV_NOHUGEPAGE_REGIONS"}, }, + { + "name": "tcmalloc_demand_cycle_120s", + "malloc": "//tcmalloc", + "deps": ["//tcmalloc:common_8k_pages"], + "env": {"BORG_EXPERIMENTS": "TCMALLOC_DEMAND_CYCLE_120S"}, + }, ] def create_tcmalloc_library(