[llvm] [llvm-profgen] Improve sample profile density (PR #92144)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 17 18:40:22 PDT 2024


================
@@ -768,9 +745,79 @@ void ProfileGenerator::populateBoundarySamplesForAllFunctions(
   }
 }
 
+void ProfileGeneratorBase::calculateDensity(
+    const FunctionSamples &FSamples,
+    std::vector<std::pair<double, uint64_t>> &DensityList,
+    uint64_t &TotalProfileSamples) {
+  uint64_t TotalBodySamples = 0;
+  uint64_t FuncBodySize = 0;
+  for (const auto &I : FSamples.getBodySamples()) {
+    TotalBodySamples += I.second.getSamples();
+    FuncBodySize++;
+  }
+
+  // The whole function could be inlined and optimized out, use the callsite
+  // head samples instead to estimate the body count.
+  if (FuncBodySize == 0) {
+    for (const auto &CallsiteSamples : FSamples.getCallsiteSamples()) {
+      FuncBodySize++;
+      for (const auto &Callee : CallsiteSamples.second) {
+        calculateDensity(Callee.second, DensityList, TotalProfileSamples);
+        TotalBodySamples += Callee.second.getHeadSamplesEstimate();
+      }
+    }
+  }
+
+  if (FuncBodySize == 0)
+    return;
+
+  double FuncDensity = static_cast<double>(TotalBodySamples) / FuncBodySize;
+  TotalProfileSamples += TotalBodySamples;
+  DensityList.emplace_back(FuncDensity, TotalBodySamples);
+}
+
+// Calculate Profile-density:
+// Calculate the density for each function and sort them in descending order,
+// iterate them once their accumulated total samples exceeds the
+// percentage_threshold(cut-off) of total profile samples, the profile-density
+// is the last(minimum) function-density of the processed functions, which means
+// all the functions hot to perf are on good density if the profile-density is
+// good. The percentage_threshold(--profile-density-cutoff-hot) is configurable
+// depending on how much regression the system want to tolerate.
+double
+ProfileGeneratorBase::calculateDensity(const SampleProfileMap &Profiles) {
+  double ProfileDensity = 0.0;
+
+  uint64_t TotalProfileSamples = 0;
+  // A list of the function profile density and its total samples.
+  std::vector<std::pair<double, uint64_t>> FuncDensityList;
+  for (const auto &I : Profiles)
+    calculateDensity(I.second, FuncDensityList, TotalProfileSamples);
+
+  // Sorted by the density in descending order.
+  llvm::stable_sort(FuncDensityList, [&](const std::pair<double, uint64_t> &A,
+                                         const std::pair<double, uint64_t> &B) {
+    if (A.first != B.first)
+      return A.first > B.first;
+    return A.second < B.second;
+  });
+
+  uint64_t AccumulatedSamples = 0;
+  for (const auto &P : FuncDensityList) {
+    AccumulatedSamples += P.second;
+    ProfileDensity = P.first;
+    if (AccumulatedSamples >= TotalProfileSamples *
+                                  static_cast<float>(ProfileDensityCutOffHot) /
+                                  1000000)
+      break;
----------------
WenleiHe wrote:

nit: fold the exit condition into a while loop condition?

https://github.com/llvm/llvm-project/pull/92144


More information about the llvm-commits mailing list