[compiler-rt] [scudo] Dumping allocator config when printStats() (PR #191860)

Sadaf Ebrahimi via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 11:31:16 PDT 2026


https://github.com/sadafebrahimi updated https://github.com/llvm/llvm-project/pull/191860

>From b1b6ef9f966891e2619f3b8d109795610677936a Mon Sep 17 00:00:00 2001
From: Sadaf Ebrahimi <sadafebrahimi at google.com>
Date: Mon, 13 Apr 2026 16:05:41 +0000
Subject: [PATCH] [scudo] Dumping allocator config when printStats()

So far printStats() dumps partial information of the allocator config.
Given that user is able to have custom config, we want to dump all the
configurations to reduce variances while reviewing the stats.
---
 compiler-rt/lib/scudo/standalone/combined.h   | 17 ++++++++++--
 compiler-rt/lib/scudo/standalone/primary32.h  | 17 ++++++++++++
 compiler-rt/lib/scudo/standalone/primary64.h  | 19 ++++++++++++++
 compiler-rt/lib/scudo/standalone/secondary.h  | 26 +++++++++++++++++++
 .../scudo/standalone/tests/combined_test.cpp  | 18 +++++++++++++
 .../scudo/standalone/tests/secondary_test.cpp | 14 ++++++++++
 6 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 1c1a92aefd461..19bff94545cc3 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -233,8 +233,7 @@ class Allocator {
       gwp_asan::segv_handler::installSignalHandlers(
           &GuardedAlloc, Printf,
           gwp_asan::backtrace::getPrintBacktraceFunction(),
-          gwp_asan::backtrace::getSegvBacktraceFunction(),
-          Opt.Recoverable);
+          gwp_asan::backtrace::getSegvBacktraceFunction(), Opt.Recoverable);
 
     GuardedAllocSlotSize =
         GuardedAlloc.getAllocatorState()->maximumAllocationSize();
@@ -1774,7 +1773,21 @@ class Allocator {
     }
   }
 
+  void getConfigStats(ScopedString *Str) {
+    const bool MaySupportMemoryTagging =
+        AllocatorConfig::getMaySupportMemoryTagging();
+    const bool QuarantineDisabled = AllocatorConfig::getQuarantineDisabled();
+    const bool ExactUsableSize = AllocatorConfig::getExactUsableSize();
+    Str->append("Config Stats Combined: MaySupportMemoryTagging: %d; "
+                "QuarantineDisabled: %s; ExactUsableSize: %s\n",
+                MaySupportMemoryTagging, QuarantineDisabled ? "true" : "false",
+                ExactUsableSize ? "true" : "false");
+  }
+
   uptr getStats(ScopedString *Str) {
+    getConfigStats(Str);
+    Primary.getConfigStats(Str);
+    Secondary.getConfigStats(Str);
     Primary.getStats(Str);
     Secondary.getStats(Str);
     if (!AllocatorConfig::getQuarantineDisabled())
diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h
index 037fa3d7a7dcb..a4ace644b30b2 100644
--- a/compiler-rt/lib/scudo/standalone/primary32.h
+++ b/compiler-rt/lib/scudo/standalone/primary32.h
@@ -119,6 +119,7 @@ template <typename Config> class SizeClassAllocator32 {
   template <typename F> void iterateOverBlocks(F Callback);
 
   void getStats(ScopedString *Str);
+  void getConfigStats(ScopedString *Str);
   void getFragmentationInfo(ScopedString *Str);
   void getMemoryGroupFragmentationInfo(ScopedString *Str) {
     // Each region is also a memory group because region size is the same as
@@ -451,6 +452,22 @@ void SizeClassAllocator32<Config>::iterateOverBlocks(F Callback) {
   }
 }
 
+template <typename Config>
+void SizeClassAllocator32<Config>::getConfigStats(ScopedString *Str) {
+  const uptr RegionSizeLog = Config::getRegionSizeLog();
+  const uptr GroupSizeLog = Config::getGroupSizeLog();
+  const bool EnableBlockCache = Config::getEnableBlockCache();
+  const uptr CompactPtrScale = Config::getCompactPtrScale();
+  const bool EnableRandomOffset = Config::getEnableRandomOffset();
+  const bool EnableContiguousRegions = Config::getEnableContiguousRegions();
+  Str->append("Config Stats Primary64: RegionSizeLog: %zu; GroupSizeLog: %zu; "
+              "EnableBlockCache: %s; CompactPtrScale: %zu; EnableRandomOffset: "
+              "%s; EnableContiguousRegions: %s\n",
+              RegionSizeLog, GroupSizeLog, EnableBlockCache ? "true" : "false",
+              CompactPtrScale, EnableRandomOffset ? "true" : "false",
+              EnableContiguousRegions ? "true" : "false");
+}
+
 template <typename Config>
 void SizeClassAllocator32<Config>::getStats(ScopedString *Str) {
   // TODO(kostyak): get the RSS per region.
diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h
index a185d497e4963..4f8e7a9a99993 100644
--- a/compiler-rt/lib/scudo/standalone/primary64.h
+++ b/compiler-rt/lib/scudo/standalone/primary64.h
@@ -113,6 +113,7 @@ template <typename Config> class SizeClassAllocator64 {
   template <typename F> void iterateOverBlocks(F Callback);
 
   void getStats(ScopedString *Str);
+  void getConfigStats(ScopedString *Str);
   void getFragmentationInfo(ScopedString *Str);
   void getMemoryGroupFragmentationInfo(ScopedString *Str);
 
@@ -1099,6 +1100,24 @@ void SizeClassAllocator64<Config>::iterateOverBlocks(F Callback) {
   }
 }
 
+template <typename Config>
+void SizeClassAllocator64<Config>::getConfigStats(ScopedString *Str) {
+  const uptr RegionSizeLog = Config::getRegionSizeLog();
+  const uptr GroupSizeLog = Config::getGroupSizeLog();
+  const uptr MapSizeIncrement = Config::getMapSizeIncrement();
+  const bool EnableBlockCache = Config::getEnableBlockCache();
+  const uptr CompactPtrScale = Config::getCompactPtrScale();
+  const bool EnableRandomOffset = Config::getEnableRandomOffset();
+  const bool EnableContiguousRegions = Config::getEnableContiguousRegions();
+  Str->append("Config Stats Primary64: RegionSizeLog: %zu; GroupSizeLog: %zu; "
+              "MapSizeIncrement: %zu; EnableBlockCache: %s; CompactPtrScale: "
+              "%zu; EnableRandomOffset: %s; EnableContiguousRegions: %s\n",
+              RegionSizeLog, GroupSizeLog, MapSizeIncrement,
+              EnableBlockCache ? "true" : "false", CompactPtrScale,
+              EnableRandomOffset ? "true" : "false",
+              EnableContiguousRegions ? "true" : "false");
+}
+
 template <typename Config>
 void SizeClassAllocator64<Config>::getStats(ScopedString *Str) {
   // TODO(kostyak): get the RSS per region.
diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h
index a740836a144c5..a231873bf3f58 100644
--- a/compiler-rt/lib/scudo/standalone/secondary.h
+++ b/compiler-rt/lib/scudo/standalone/secondary.h
@@ -142,6 +142,10 @@ template <typename Config> class MapAllocatorNoCache {
     return true;
   }
 
+  void getConfigStats(ScopedString *Str) {
+    Str->append("Secondary Cache Disabled\n");
+  }
+
   void getStats(UNUSED ScopedString *Str) {
     Str->append("Secondary Cache Disabled\n");
   }
@@ -212,6 +216,18 @@ template <typename T> class NonZeroLengthArray<T, 0> {
 template <typename Config, void (*unmapCallBack)(MemMapT &) = unmap>
 class MapAllocatorCache {
 public:
+  void getConfigStats(ScopedString *Str) {
+    const u32 EntriesArraySize = Config::getEntriesArraySize();
+    const u32 QuarantineSize = Config::getQuarantineSize();
+    const u32 DefaultMaxEntriesCount = Config::getDefaultMaxEntriesCount();
+    const uptr DefaultMaxEntrySize = Config::getDefaultMaxEntrySize();
+    Str->append("EntriesArraySize: %" PRIu32 "; QuarantineSize: %" PRIu32
+                "; DefaultMaxEntriesCount: %" PRIu32
+                "; DefaultMaxEntrySize: %zu\n",
+                EntriesArraySize, QuarantineSize, DefaultMaxEntriesCount,
+                DefaultMaxEntrySize);
+  }
+
   void getStats(ScopedString *Str) {
     ScopedLock L(Mutex);
     uptr Integral;
@@ -728,6 +744,8 @@ template <typename Config> class MapAllocator {
 
   void unmapTestOnly() { Cache.unmapTestOnly(); }
 
+  void getConfigStats(ScopedString *Str);
+
   void getStats(ScopedString *Str);
 
 private:
@@ -952,6 +970,14 @@ void MapAllocator<Config>::deallocate(const Options &Options, void *Ptr)
   }
 }
 
+template <typename Config>
+void MapAllocator<Config>::getConfigStats(ScopedString *Str) EXCLUDES(Mutex) {
+  const bool EnableGuardPages = Config::getEnableGuardPages();
+  Str->append("Config Stats Secondary: EnableGuardPages: %s; ",
+              EnableGuardPages ? "true" : "false");
+  Cache.getConfigStats(Str);
+}
+
 template <typename Config>
 void MapAllocator<Config>::getStats(ScopedString *Str) EXCLUDES(Mutex) {
   ScopedLock L(Mutex);
diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
index 6a34e8be11151..58529a96ce04e 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -1220,6 +1220,15 @@ struct TestQuarantineDisabledConfig : TestQuarantineConfig {
   static const bool QuarantineDisabled = true;
 };
 
+TEST(ScudoCombinedTest, QuarantineDisabledConfigStats) {
+  using AllocatorT = TestAllocator<TestQuarantineDisabledConfig>;
+  auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
+
+  std::string Stats(10000, '\0');
+  Allocator->getStats(Stats.data(), Stats.size());
+  EXPECT_NE(Stats.find("QuarantineDisabled: true"), std::string::npos);
+}
+
 TEST(ScudoCombinedTest, QuarantineDisabled) {
   using AllocatorT = TestAllocator<TestQuarantineDisabledConfig>;
   auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
@@ -1456,6 +1465,15 @@ struct TestFullUsableSizeConfig : TestExactUsableSizeConfig {
   static const bool ExactUsableSize = false;
 };
 
+TEST(ScudoCombinedTest, ExactUsableSizeConfigStats) {
+  using AllocatorT = TestAllocator<TestFullUsableSizeConfig>;
+  auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
+
+  std::string Stats(10000, '\0');
+  Allocator->getStats(Stats.data(), Stats.size());
+  EXPECT_NE(Stats.find("ExactUsableSize: false"), std::string::npos);
+}
+
 TEST(ScudoCombinedTest, FullUsableSize) {
   using AllocatorT = scudo::Allocator<TestFullUsableSizeConfig>;
   auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
diff --git a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
index 8741c8299b57c..73a6be77ccdea 100644
--- a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
@@ -184,6 +184,20 @@ TEST(ScudoSecondaryTest, Basic) {
   testBasic<scudo::DefaultConfig>();
 }
 
+template <typename Config> static void testConfigStatsBool() {
+  AllocatorInfoType<Config> Info;
+
+  scudo::ScopedString Str;
+  Info.Allocator->getConfigStats(&Str);
+  std::string Output(Str.data());
+  EXPECT_TRUE(Output.find("EnableGuardPages: false") != std::string::npos);
+}
+
+TEST(ScudoSecondaryTest, ConfigStatsBool) {
+  testConfigStatsBool<TestNoCacheNoGuardPageConfig>();
+  testConfigStatsBool<TestCacheNoGuardPageConfig>();
+}
+
 // This exercises a variety of combinations of size and alignment for the
 // MapAllocator. The size computation done here mimic the ones done by the
 // combined allocator.



More information about the llvm-commits mailing list