[compiler-rt] [scudo] Add unmap and eviction stats to Secondary (PR #210465)
Sadaf Ebrahimi via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 17 16:55:35 PDT 2026
https://github.com/sadafebrahimi created https://github.com/llvm/llvm-project/pull/210465
Track and print stats on the number of memory unmaps and cache evictions in the MapAllocator. These statistics track total unmaps, as well as unmaps triggered by exceeding the maximum cache entry size or the maximum number of entries in the cache.
>From 19786779b3bf28b6503fcfe1ad4a96fba647d3b1 Mon Sep 17 00:00:00 2001
From: Sadaf Ebrahimi <sadafebrahimi at google.com>
Date: Fri, 17 Jul 2026 23:48:14 +0000
Subject: [PATCH] [scudo] Add unmap and eviction stats to Secondary
Track and print stats on the number of memory unmaps and cache evictions
in the MapAllocator. These statistics track total unmaps, as well as
unmaps triggered by exceeding the maximum cache entry size or the
maximum number of entries in the cache.
---
compiler-rt/lib/scudo/standalone/secondary.h | 31 ++++++++++++++++++-
.../scudo/standalone/tests/secondary_test.cpp | 7 +++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h
index b4a5685080b03..4fa4512147647 100644
--- a/compiler-rt/lib/scudo/standalone/secondary.h
+++ b/compiler-rt/lib/scudo/standalone/secondary.h
@@ -72,7 +72,25 @@ template <typename Config> Header *getHeader(const void *Ptr) {
} // namespace LargeBlock
-static inline void unmap(MemMapT &MemMap) { MemMap.unmap(); }
+static inline void unmap(MemMapT &MemMap) {
+ atomic_fetch_add(getUnmapCount(), 1ULL, memory_order_relaxed);
+ MemMap.unmap();
+}
+
+inline atomic_u64 *getUnmapCount() {
+ static atomic_u64 Count = {};
+ return &Count;
+}
+
+inline atomic_u64 *getEvictedCount() {
+ static atomic_u64 Count = {};
+ return &Count;
+}
+
+inline atomic_u64 *getEvictedBySizeCount() {
+ static atomic_u64 Count = {};
+ return &Count;
+}
namespace {
@@ -234,6 +252,15 @@ class MapAllocatorCache {
Str->append("Stats: CacheRetrievalStats: SuccessRate: %u/%u "
"(%zu.%02zu%%)\n",
SuccessfulRetrieves, CallsToRetrieve, Integral, Fractional);
+ Str->append(
+ "Total Unmaps: %llu\n",
+ static_cast<unsigned long long>(atomic_load_relaxed(getUnmapCount())));
+ Str->append("Unmapped (exceeded MaxEntrySize): %llu\n",
+ static_cast<unsigned long long>(
+ atomic_load_relaxed(getEvictedBySizeCount())));
+ Str->append("Unmapped (exceeded DefaultMaxEntriesCount): %llu\n",
+ static_cast<unsigned long long>(
+ atomic_load_relaxed(getEvictedCount())));
Str->append("Cache Entry Info (Most Recent -> Least Recent):\n");
for (CachedBlock &Entry : LRUEntries) {
@@ -366,6 +393,7 @@ class MapAllocatorCache {
while (LRUEntries.size() >= atomic_load_relaxed(&MaxEntriesCount)) {
// Save MemMaps of evicted entries to perform unmap outside of lock
CachedBlock *Entry = LRUEntries.back();
+ atomic_fetch_add(getEvictedCount(), 1ULL, memory_order_relaxed);
EvictionMemMaps.push_back(Entry->MemMap);
remove(Entry);
}
@@ -957,6 +985,7 @@ void MapAllocator<Config>::deallocate(const Options &Options, void *Ptr)
// Note that the `H->MemMap` is stored on the pages managed by itself. Take
// over the ownership before unmap() so that any operation along with
// unmap() won't touch inaccessible pages.
+ atomic_fetch_add(getEvictedBySizeCount(), 1ULL, memory_order_relaxed);
MemMapT MemMap = H->MemMap;
unmap(MemMap);
}
diff --git a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
index e6ceb2d8b9317..bbfec2aab79b7 100644
--- a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp
@@ -478,6 +478,13 @@ TEST(ScudoSecondaryTest, AllocatorCacheMemoryLeakTest) {
// Evicted entry should be marked due to unmap callback
EXPECT_EQ(*reinterpret_cast<scudo::u32 *>(Info.MemMaps[0].getBase()),
UnmappedMarker);
+ scudo::ScopedString Str;
+ Info.Cache->getStats(&Str);
+ Str.output();
+ EXPECT_NE(strstr(Str.data(), "Total Unmaps: 0"), nullptr);
+ EXPECT_NE(strstr(Str.data(), "Unmapped (exceeded MaxEntrySize): 0"), nullptr);
+ EXPECT_NE(strstr(Str.data(), "Unmapped (exceeded DefaultMaxEntriesCount): 1"),
+ nullptr)
}
TEST(ScudoSecondaryTest, AllocatorCacheOptions) {
More information about the llvm-commits
mailing list