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