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

Sadaf Ebrahimi via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 14:47:22 PDT 2026


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

>From c54149ba04c0cf7bcf20925c76ce97e65ded5503 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   |  18 ++-
 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  | 108 ++++++++++++++++++
 .../scudo/standalone/tests/secondary_test.cpp |  14 +++
 6 files changed, 200 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 1c1a92aefd461..14cd0d718b058 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,22 @@ 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: %s; "
+                "QuarantineDisabled: %s; ExactUsableSize: %s\n",
+                MaySupportMemoryTagging ? "true" : "false",
+                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..f4588bd390d03 100644
--- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp
@@ -1893,3 +1893,111 @@ TEST(ScudoCombinedTest, VerifyConfigOverrideMatchChecks) {
     Allocator->deallocateAligned(Ptr, scudo::Chunk::Origin::Malloc, Alignment);
   }
 }
+
+struct TestAllBoolFalseConfig {
+  static const bool MaySupportMemoryTagging = false;
+  static const bool QuarantineDisabled = false;
+  static const bool ExactUsableSize = false;
+  template <class A> using TSDRegistryT = scudo::TSDRegistrySharedT<A, 8U, 4U>;
+
+  struct Primary {
+    using SizeClassMap = scudo::AndroidSizeClassMap;
+    static const scudo::uptr RegionSizeLog = 18U;
+    static const scudo::uptr GroupSizeLog = 18U;
+#if SCUDO_CAN_USE_PRIMARY64
+    static const scudo::uptr MapSizeIncrement = 1UL << 18;
+#endif
+    static const bool EnableBlockCache = false;
+    static const scudo::uptr CompactPtrScale = 0;
+    static const bool EnableRandomOffset = false;
+    static const bool EnableContiguousRegions = false;
+  };
+
+#if SCUDO_CAN_USE_PRIMARY64
+  template <typename Config>
+  using PrimaryT = scudo::SizeClassAllocator64<Config>;
+#else
+  template <typename Config>
+  using PrimaryT = scudo::SizeClassAllocator32<Config>;
+#endif
+
+  struct Secondary {
+    template <typename Config>
+    using CacheT = scudo::MapAllocatorNoCache<Config>;
+  };
+  template <typename Config> using SecondaryT = scudo::MapAllocator<Config>;
+};
+
+TEST(ScudoCombinedTest, VerifyAllBoolFalseConfig) {
+  using AllocatorT = scudo::Allocator<TestAllBoolFalseConfig>;
+  auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
+
+  std::string Stats(10000, '\0');
+  Allocator->getStats(Stats.data(), Stats.size());
+  EXPECT_NE(Stats.find("MaySupportMemoryTagging: false"), std::string::npos);
+  EXPECT_NE(Stats.find("QuarantineDisabled: false"), std::string::npos);
+  EXPECT_NE(Stats.find("ExactUsableSize: false"), std::string::npos);
+  EXPECT_NE(Stats.find("RegionSizeLog: 18"), std::string::npos);
+  EXPECT_NE(Stats.find("GroupSizeLog: 18"), std::string::npos);
+#if SCUDO_CAN_USE_PRIMARY64
+  EXPECT_NE(Stats.find("MapSizeIncrement: 262144"), std::string::npos);
+#endif
+  EXPECT_NE(Stats.find("EnableBlockCache: false"), std::string::npos);
+  EXPECT_NE(Stats.find("CompactPtrScale: 0"), std::string::npos);
+  EXPECT_NE(Stats.find("EnableRandomOffset: false"), std::string::npos);
+  EXPECT_NE(Stats.find("EnableContiguousRegions: false"), std::string::npos);
+}
+
+struct TestAllBoolTrueConfig {
+  static const bool MaySupportMemoryTagging = true;
+  static const bool QuarantineDisabled = true;
+  static const bool ExactUsableSize = true;
+  template <class A> using TSDRegistryT = scudo::TSDRegistrySharedT<A, 8U, 4U>;
+
+  struct Primary {
+    using SizeClassMap = scudo::AndroidSizeClassMap;
+    static const scudo::uptr RegionSizeLog = 18U;
+    static const scudo::uptr GroupSizeLog = 18U;
+#if SCUDO_CAN_USE_PRIMARY64
+    static const scudo::uptr MapSizeIncrement = 1UL << 18;
+#endif
+    static const bool EnableBlockCache = true;
+    static const scudo::uptr CompactPtrScale = 0;
+    static const bool EnableRandomOffset = true;
+    static const bool EnableContiguousRegions = true;
+  };
+
+#if SCUDO_CAN_USE_PRIMARY64
+  template <typename Config>
+  using PrimaryT = scudo::SizeClassAllocator64<Config>;
+#else
+  template <typename Config>
+  using PrimaryT = scudo::SizeClassAllocator32<Config>;
+#endif
+
+  struct Secondary {
+    template <typename Config>
+    using CacheT = scudo::MapAllocatorNoCache<Config>;
+  };
+  template <typename Config> using SecondaryT = scudo::MapAllocator<Config>;
+};
+
+TEST(ScudoCombinedTest, VerifyAllBoolTrueConfig) {
+  using AllocatorT = scudo::Allocator<TestAllBoolTrueConfig>;
+  auto Allocator = std::unique_ptr<AllocatorT>(new AllocatorT());
+
+  std::string Stats(10000, '\0');
+  Allocator->getStats(Stats.data(), Stats.size());
+  EXPECT_NE(Stats.find("MaySupportMemoryTagging: true"), std::string::npos);
+  EXPECT_NE(Stats.find("QuarantineDisabled: true"), std::string::npos);
+  EXPECT_NE(Stats.find("ExactUsableSize: true"), std::string::npos);
+  EXPECT_NE(Stats.find("RegionSizeLog: 18"), std::string::npos);
+  EXPECT_NE(Stats.find("GroupSizeLog: 18"), std::string::npos);
+#if SCUDO_CAN_USE_PRIMARY64
+  EXPECT_NE(Stats.find("MapSizeIncrement: 262144"), std::string::npos);
+#endif
+  EXPECT_NE(Stats.find("EnableBlockCache: true"), std::string::npos);
+  EXPECT_NE(Stats.find("CompactPtrScale: 0"), std::string::npos);
+  EXPECT_NE(Stats.find("EnableRandomOffset: true"), std::string::npos);
+  EXPECT_NE(Stats.find("EnableContiguousRegions: true"), std::string::npos);
+}
\ No newline at end of file
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