Skip to content

Commit 955fcb1

Browse files
committed
Add memory usage statistics for allocation classes
This includes printing: - allocSize - allocated memory size - memory usage fraction
1 parent 519f664 commit 955fcb1

File tree

10 files changed

+107
-8
lines changed

10 files changed

+107
-8
lines changed

cachelib/allocator/Cache.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ class CacheBase {
102102
// @param poolId the pool id
103103
virtual PoolStats getPoolStats(PoolId poolId) const = 0;
104104

105+
// Get Allocation Class specific stats.
106+
//
107+
// @param poolId the pool id
108+
// @param classId the class id
109+
virtual ACStats getACStats(PoolId poolId, ClassId classId) const = 0;
110+
105111
// @param poolId the pool id
106112
virtual AllSlabReleaseEvents getAllSlabReleaseEvents(PoolId poolId) const = 0;
107113

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,14 @@ PoolStats CacheAllocator<CacheTrait>::getPoolStats(PoolId poolId) const {
22202220
return ret;
22212221
}
22222222

2223+
template <typename CacheTrait>
2224+
ACStats CacheAllocator<CacheTrait>::getACStats(PoolId poolId,
2225+
ClassId classId) const {
2226+
const auto& pool = allocator_->getPool(poolId);
2227+
const auto& ac = pool.getAllocationClass(classId);
2228+
return ac.getStats();
2229+
}
2230+
22232231
template <typename CacheTrait>
22242232
PoolEvictionAgeStats CacheAllocator<CacheTrait>::getPoolEvictionAgeStats(
22252233
PoolId pid, unsigned int slabProjectionLength) const {

cachelib/allocator/CacheAllocator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,9 @@ class CacheAllocator : public CacheBase {
11751175
// return cache's memory usage stats
11761176
CacheMemoryStats getCacheMemoryStats() const override final;
11771177

1178+
// return stats for Allocation Class
1179+
ACStats getACStats(PoolId pid, ClassId cid) const override final;
1180+
11781181
// return the nvm cache stats map
11791182
util::StatsMap getNvmCacheStatsMap() const override final;
11801183

cachelib/allocator/memory/AllocationClass.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,6 @@ class AllocationClass {
9494
return static_cast<unsigned int>(Slab::kSize / allocationSize_);
9595
}
9696

97-
// total number of slabs under this AllocationClass.
98-
unsigned int getNumSlabs() const {
99-
return lock_->lock_combine([this]() {
100-
return static_cast<unsigned int>(freeSlabs_.size() +
101-
allocatedSlabs_.size());
102-
});
103-
}
104-
10597
// fetch stats about this allocation class.
10698
ACStats getStats() const;
10799

cachelib/allocator/memory/MemoryAllocatorStats.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ struct ACStats {
5454
constexpr size_t getTotalFreeMemory() const noexcept {
5555
return Slab::kSize * freeSlabs + freeAllocs * allocSize;
5656
}
57+
58+
constexpr double usageFraction() const noexcept {
59+
if (usedSlabs == 0)
60+
return 0.0;
61+
62+
return activeAllocs / (usedSlabs * allocsPerSlab);
63+
}
64+
65+
constexpr size_t totalAllocatedSize() const noexcept {
66+
return activeAllocs * allocSize;
67+
}
5768
};
5869

5970
// structure to query stats corresponding to a MemoryPool

cachelib/allocator/tests/CacheBaseTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class CacheBaseTest : public CacheBase, public SlabAllocatorTestBase {
3434
bool isObjectCache() const override { return false; }
3535
const MemoryPool& getPool(PoolId) const override { return memoryPool_; }
3636
PoolStats getPoolStats(PoolId) const override { return PoolStats(); }
37+
ACStats getACStats(PoolId, ClassId) const { return ACStats(); };
3738
AllSlabReleaseEvents getAllSlabReleaseEvents(PoolId) const override {
3839
return AllSlabReleaseEvents{};
3940
}

cachelib/cachebench/cache/Cache-inl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,19 @@ Stats Cache<Allocator>::getStats() const {
609609
aggregate += poolStats;
610610
}
611611

612+
std::map<PoolId, std::map<ClassId, ACStats>> allocationClassStats{};
613+
614+
for (size_t pid = 0; pid < pools_.size(); pid++) {
615+
auto cids = cache_->getPoolStats(static_cast<PoolId>(pid)).getClassIds();
616+
for (auto cid : cids)
617+
allocationClassStats[pid][cid] = cache_->getACStats(pid, cid);
618+
}
619+
612620
const auto cacheStats = cache_->getGlobalCacheStats();
613621
const auto rebalanceStats = cache_->getSlabReleaseStats();
614622
const auto navyStats = cache_->getNvmCacheStatsMap().toMap();
615623

624+
ret.allocationClassStats = allocationClassStats;
616625
ret.numEvictions = aggregate.numEvictions();
617626
ret.numItems = aggregate.numItems();
618627
ret.evictAttempts = cacheStats.evictionAttempts;

cachelib/cachebench/cache/Cache.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ DEFINE_bool(report_api_latency,
2020
false,
2121
"Enable reporting cache API latency tracking");
2222

23+
DEFINE_string(
24+
report_ac_memory_usage_stats,
25+
"",
26+
"Enable reporting statistics for each allocation class. Set to"
27+
"'human_readable' to print KB/MB/GB or to 'raw' to print in bytes.");
28+
2329
namespace facebook {
2430
namespace cachelib {
2531
namespace cachebench {} // namespace cachebench

cachelib/cachebench/cache/Cache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "cachelib/cachebench/util/NandWrites.h"
4545

4646
DECLARE_bool(report_api_latency);
47+
DECLARE_string(report_ac_memory_usage_stats);
4748

4849
namespace facebook {
4950
namespace cachelib {
@@ -324,6 +325,10 @@ class Cache {
324325
// return the stats for the pool.
325326
PoolStats getPoolStats(PoolId pid) const { return cache_->getPoolStats(pid); }
326327

328+
ACStats getACStats(PoolId pid, ClassId cid) const {
329+
return cache_->getACStats(pid, cid);
330+
}
331+
327332
// return the total number of inconsistent operations detected since start.
328333
unsigned int getInconsistencyCount() const {
329334
return inconsistencyCount_.load(std::memory_order_relaxed);

cachelib/cachebench/cache/CacheStats.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "cachelib/common/PercentileStats.h"
2222

2323
DECLARE_bool(report_api_latency);
24+
DECLARE_string(report_ac_memory_usage_stats);
2425

2526
namespace facebook {
2627
namespace cachelib {
@@ -100,6 +101,8 @@ struct Stats {
100101
uint64_t invalidDestructorCount{0};
101102
int64_t unDestructedItemCount{0};
102103

104+
std::map<PoolId, std::map<ClassId, ACStats>> allocationClassStats;
105+
103106
// populate the counters related to nvm usage. Cache implementation can decide
104107
// what to populate since not all of those are interesting when running
105108
// cachebench.
@@ -131,6 +134,61 @@ struct Stats {
131134
<< std::endl;
132135
}
133136

137+
if (FLAGS_report_ac_memory_usage_stats != "") {
138+
auto formatMemory = [&](size_t bytes) -> std::tuple<std::string, double> {
139+
if (FLAGS_report_ac_memory_usage_stats == "raw") {
140+
return {"B", bytes};
141+
}
142+
143+
constexpr double KB = 1024.0;
144+
constexpr double MB = 1024.0 * 1024;
145+
constexpr double GB = 1024.0 * 1024 * 1024;
146+
147+
if (bytes >= GB) {
148+
return {"GB", static_cast<double>(bytes) / GB};
149+
} else if (bytes >= MB) {
150+
return {"MB", static_cast<double>(bytes) / MB};
151+
} else if (bytes >= KB) {
152+
return {"KB", static_cast<double>(bytes) / KB};
153+
} else {
154+
return {"B", bytes};
155+
}
156+
};
157+
158+
auto foreachAC = [&](auto cb) {
159+
for (auto& pidStat : allocationClassStats) {
160+
for (auto& cidStat : pidStat.second) {
161+
cb(pidStat.first, cidStat.first, cidStat.second);
162+
}
163+
}
164+
};
165+
166+
foreachAC([&](auto pid, auto cid, auto stats) {
167+
auto [allocSizeSuffix, allocSize] = formatMemory(stats.allocSize);
168+
auto [memorySizeSuffix, memorySize] =
169+
formatMemory(stats.totalAllocatedSize());
170+
out << folly::sformat("pid{:2} cid{:4} {:8.2f}{} memorySize: {:8.2f}{}",
171+
pid, cid, allocSize, allocSizeSuffix, memorySize,
172+
memorySizeSuffix)
173+
<< std::endl;
174+
});
175+
176+
foreachAC([&](auto pid, auto cid, auto stats) {
177+
auto [allocSizeSuffix, allocSize] = formatMemory(stats.allocSize);
178+
179+
// If the pool is not full, extrapolate usageFraction for AC assuming it
180+
// will grow at the same rate. This value will be the same for all ACs.
181+
auto acUsageFraction = (poolUsageFraction[pid] < 1.0)
182+
? poolUsageFraction[pid]
183+
: stats.usageFraction();
184+
185+
out << folly::sformat(
186+
"pid{:2} cid{:4} {:8.2f}{} usageFraction: {:4.2f}", pid, cid,
187+
allocSize, allocSizeSuffix, acUsageFraction)
188+
<< std::endl;
189+
});
190+
}
191+
134192
if (numCacheGets > 0) {
135193
out << folly::sformat("Cache Gets : {:,}", numCacheGets) << std::endl;
136194
out << folly::sformat("Hit Ratio : {:6.2f}%", overallHitRatio)

0 commit comments

Comments
 (0)