xref: /llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-statistics.cpp (revision 7c36b416b6b1f8ff9a689ad4c33ef921259d04d5)
1 //===-- llvm-jitlink-statistics.cpp -- gathers/reports JIT-linking stats --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the code for enabling, gathering and reporting
10 // llvm-jitlink statistics.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm-jitlink.h"
15 #include "llvm/Support/CommandLine.h"
16 
17 #define DEBUG_TYPE "llvm_jitlink"
18 
19 using namespace llvm;
20 using namespace llvm::jitlink;
21 using namespace llvm::orc;
22 
23 static cl::opt<bool> ShowPrePruneTotalBlockSize(
24     "pre-prune-total-block-size",
25     cl::desc("Total size of all blocks (including zero-fill) in all "
26              "graphs (pre-pruning)"),
27     cl::init(false));
28 
29 static cl::opt<bool> ShowPostFixupTotalBlockSize(
30     "post-fixup-total-block-size",
31     cl::desc("Total size of all blocks (including zero-fill) in all "
32              "graphs (post-fixup)"),
33     cl::init(false));
34 
35 class StatsPlugin : public ObjectLinkingLayer::Plugin {
36 public:
enableIfNeeded(Session & S,bool UsingOrcRuntime)37   static void enableIfNeeded(Session &S, bool UsingOrcRuntime) {
38     std::unique_ptr<StatsPlugin> Instance;
39     auto GetStats = [&]() -> StatsPlugin & {
40       if (!Instance)
41         Instance.reset(new StatsPlugin(UsingOrcRuntime));
42       return *Instance;
43     };
44 
45     if (ShowPrePruneTotalBlockSize)
46       GetStats().PrePruneTotalBlockSize = 0;
47 
48     if (ShowPostFixupTotalBlockSize)
49       GetStats().PostFixupTotalBlockSize = 0;
50 
51     if (Instance)
52       S.ObjLayer.addPlugin(std::move(Instance));
53   }
54 
~StatsPlugin()55   ~StatsPlugin() { publish(dbgs()); }
56 
57   void publish(raw_ostream &OS);
58 
modifyPassConfig(MaterializationResponsibility & MR,LinkGraph & G,PassConfiguration & PassConfig)59   void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G,
60                         PassConfiguration &PassConfig) override {
61     PassConfig.PrePrunePasses.push_back(
62         [this](LinkGraph &G) { return recordPrePruneStats(G); });
63     PassConfig.PostFixupPasses.push_back(
64         [this](LinkGraph &G) { return recordPostFixupStats(G); });
65   }
66 
notifyFailed(MaterializationResponsibility & MR)67   Error notifyFailed(MaterializationResponsibility &MR) override {
68     return Error::success();
69   }
70 
notifyRemovingResources(JITDylib & JD,ResourceKey K)71   Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
72     return Error::success();
73   }
74 
notifyTransferringResources(JITDylib & JD,ResourceKey DstKey,ResourceKey SrcKey)75   void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
76                                    ResourceKey SrcKey) override {}
77 
78 private:
StatsPlugin(bool UsingOrcRuntime)79   StatsPlugin(bool UsingOrcRuntime) : UsingOrcRuntime(UsingOrcRuntime) {}
80   Error recordPrePruneStats(jitlink::LinkGraph &G);
81   Error recordPostFixupStats(jitlink::LinkGraph &G);
82 
83   bool UsingOrcRuntime;
84 
85   std::mutex M;
86   std::optional<uint64_t> PrePruneTotalBlockSize;
87   std::optional<uint64_t> PostFixupTotalBlockSize;
88   std::optional<DenseMap<size_t, size_t>> EdgeCountDetails;
89 };
90 
publish(raw_ostream & OS)91 void StatsPlugin::publish(raw_ostream &OS) {
92 
93   if (UsingOrcRuntime)
94     OS << "Note: Session stats include runtime and entry point lookup, but "
95           "not JITDylib initialization/deinitialization.\n";
96 
97   OS << "Statistics:\n";
98   if (PrePruneTotalBlockSize)
99     OS << "  Total size of all blocks before pruning: "
100        << *PrePruneTotalBlockSize << "\n";
101 
102   if (PostFixupTotalBlockSize)
103     OS << "  Total size of all blocks after fixups: "
104        << *PostFixupTotalBlockSize << "\n";
105 }
106 
computeTotalBlockSizes(LinkGraph & G)107 static uint64_t computeTotalBlockSizes(LinkGraph &G) {
108   uint64_t TotalSize = 0;
109   for (auto *B : G.blocks())
110     TotalSize += B->getSize();
111   return TotalSize;
112 }
113 
recordPrePruneStats(LinkGraph & G)114 Error StatsPlugin::recordPrePruneStats(LinkGraph &G) {
115   std::lock_guard<std::mutex> Lock(M);
116 
117   if (PrePruneTotalBlockSize)
118     *PrePruneTotalBlockSize += computeTotalBlockSizes(G);
119 
120   return Error::success();
121 }
122 
recordPostFixupStats(LinkGraph & G)123 Error StatsPlugin::recordPostFixupStats(LinkGraph &G) {
124   std::lock_guard<std::mutex> Lock(M);
125 
126   if (PostFixupTotalBlockSize)
127     *PostFixupTotalBlockSize += computeTotalBlockSizes(G);
128   return Error::success();
129 }
130 
131 namespace llvm {
enableStatistics(Session & S,bool UsingOrcRuntime)132 void enableStatistics(Session &S, bool UsingOrcRuntime) {
133   StatsPlugin::enableIfNeeded(S, UsingOrcRuntime);
134 }
135 } // namespace llvm
136