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(Val: 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(Val: false)); |
34 | |
35 | class StatsPlugin : public ObjectLinkingLayer::Plugin { |
36 | public: |
37 | static void enableIfNeeded(Session &S, bool UsingOrcRuntime) { |
38 | std::unique_ptr<StatsPlugin> Instance; |
39 | auto GetStats = [&]() -> StatsPlugin & { |
40 | if (!Instance) |
41 | Instance.reset(p: 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(P: std::move(Instance)); |
53 | } |
54 | |
55 | ~StatsPlugin() { publish(OS&: dbgs()); } |
56 | |
57 | void publish(raw_ostream &OS); |
58 | |
59 | void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G, |
60 | PassConfiguration &PassConfig) override { |
61 | PassConfig.PrePrunePasses.push_back( |
62 | x: [this](LinkGraph &G) { return recordPrePruneStats(G); }); |
63 | PassConfig.PostFixupPasses.push_back( |
64 | x: [this](LinkGraph &G) { return recordPostFixupStats(G); }); |
65 | } |
66 | |
67 | Error notifyFailed(MaterializationResponsibility &MR) override { |
68 | return Error::success(); |
69 | } |
70 | |
71 | Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { |
72 | return Error::success(); |
73 | } |
74 | |
75 | void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, |
76 | ResourceKey SrcKey) override {} |
77 | |
78 | private: |
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 | |
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 | |
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 | |
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 | |
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 { |
132 | void enableStatistics(Session &S, bool UsingOrcRuntime) { |
133 | StatsPlugin::enableIfNeeded(S, UsingOrcRuntime); |
134 | } |
135 | } // namespace llvm |
136 | |