|  | 
| 21 | 21 | #include "cachelib/common/PercentileStats.h" | 
| 22 | 22 | 
 | 
| 23 | 23 | DECLARE_bool(report_api_latency); | 
|  | 24 | +DECLARE_string(report_ac_memory_usage_stats); | 
| 24 | 25 | 
 | 
| 25 | 26 | namespace facebook { | 
| 26 | 27 | namespace cachelib { | 
| @@ -100,6 +101,8 @@ struct Stats { | 
| 100 | 101 |   uint64_t invalidDestructorCount{0}; | 
| 101 | 102 |   int64_t unDestructedItemCount{0}; | 
| 102 | 103 | 
 | 
|  | 104 | +  std::map<PoolId, std::map<ClassId, ACStats>> allocationClassStats; | 
|  | 105 | + | 
| 103 | 106 |   // populate the counters related to nvm usage. Cache implementation can decide | 
| 104 | 107 |   // what to populate since not all of those are interesting when running | 
| 105 | 108 |   // cachebench. | 
| @@ -131,6 +134,61 @@ struct Stats { | 
| 131 | 134 |           << std::endl; | 
| 132 | 135 |     } | 
| 133 | 136 | 
 | 
|  | 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 | + | 
| 134 | 192 |     if (numCacheGets > 0) { | 
| 135 | 193 |       out << folly::sformat("Cache Gets    : {:,}", numCacheGets) << std::endl; | 
| 136 | 194 |       out << folly::sformat("Hit Ratio     : {:6.2f}%", overallHitRatio) | 
|  | 
0 commit comments