aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-jitlink/llvm-jitlink-statistics.cpp
blob: 11797952aac9a7c88c2f87bd4fdb9e10fa88b1e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//===-- llvm-jitlink-statistics.cpp -- gathers/reports JIT-linking stats --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the code for enabling, gathering and reporting
// llvm-jitlink statistics.
//
//===----------------------------------------------------------------------===//

#include "llvm-jitlink.h"
#include "llvm/Support/CommandLine.h"

#define DEBUG_TYPE "llvm_jitlink"

using namespace llvm;
using namespace llvm::jitlink;
using namespace llvm::orc;

static cl::opt<bool> ShowPrePruneTotalBlockSize(
    "pre-prune-total-block-size",
    cl::desc("Total size of all blocks (including zero-fill) in all "
             "graphs (pre-pruning)"),
    cl::init(false));

static cl::opt<bool> ShowPostFixupTotalBlockSize(
    "post-fixup-total-block-size",
    cl::desc("Total size of all blocks (including zero-fill) in all "
             "graphs (post-fixup)"),
    cl::init(false));

class StatsPlugin : public ObjectLinkingLayer::Plugin {
public:
  static void enableIfNeeded(Session &S, bool UsingOrcRuntime) {
    std::unique_ptr<StatsPlugin> Instance;
    auto GetStats = [&]() -> StatsPlugin & {
      if (!Instance)
        Instance.reset(new StatsPlugin(UsingOrcRuntime));
      return *Instance;
    };

    if (ShowPrePruneTotalBlockSize)
      GetStats().PrePruneTotalBlockSize = 0;

    if (ShowPostFixupTotalBlockSize)
      GetStats().PostFixupTotalBlockSize = 0;

    if (Instance)
      S.ObjLayer.addPlugin(std::move(Instance));
  }

  ~StatsPlugin() { publish(dbgs()); }

  void publish(raw_ostream &OS);

  void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G,
                        PassConfiguration &PassConfig) override {
    PassConfig.PrePrunePasses.push_back(
        [this](LinkGraph &G) { return recordPrePruneStats(G); });
    PassConfig.PostFixupPasses.push_back(
        [this](LinkGraph &G) { return recordPostFixupStats(G); });
  }

  Error notifyFailed(MaterializationResponsibility &MR) override {
    return Error::success();
  }

  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
    return Error::success();
  }

  void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
                                   ResourceKey SrcKey) override {}

private:
  StatsPlugin(bool UsingOrcRuntime) : UsingOrcRuntime(UsingOrcRuntime) {}
  Error recordPrePruneStats(jitlink::LinkGraph &G);
  Error recordPostFixupStats(jitlink::LinkGraph &G);

  bool UsingOrcRuntime;

  std::mutex M;
  std::optional<uint64_t> PrePruneTotalBlockSize;
  std::optional<uint64_t> PostFixupTotalBlockSize;
  std::optional<DenseMap<size_t, size_t>> EdgeCountDetails;
};

void StatsPlugin::publish(raw_ostream &OS) {

  if (UsingOrcRuntime)
    OS << "Note: Session stats include runtime and entry point lookup, but "
          "not JITDylib initialization/deinitialization.\n";

  OS << "Statistics:\n";
  if (PrePruneTotalBlockSize)
    OS << "  Total size of all blocks before pruning: "
       << *PrePruneTotalBlockSize << "\n";

  if (PostFixupTotalBlockSize)
    OS << "  Total size of all blocks after fixups: "
       << *PostFixupTotalBlockSize << "\n";
}

static uint64_t computeTotalBlockSizes(LinkGraph &G) {
  uint64_t TotalSize = 0;
  for (auto *B : G.blocks())
    TotalSize += B->getSize();
  return TotalSize;
}

Error StatsPlugin::recordPrePruneStats(LinkGraph &G) {
  std::lock_guard<std::mutex> Lock(M);

  if (PrePruneTotalBlockSize)
    *PrePruneTotalBlockSize += computeTotalBlockSizes(G);

  return Error::success();
}

Error StatsPlugin::recordPostFixupStats(LinkGraph &G) {
  std::lock_guard<std::mutex> Lock(M);

  if (PostFixupTotalBlockSize)
    *PostFixupTotalBlockSize += computeTotalBlockSizes(G);
  return Error::success();
}

namespace llvm {
void enableStatistics(Session &S, bool UsingOrcRuntime) {
  StatsPlugin::enableIfNeeded(S, UsingOrcRuntime);
}
} // namespace llvm