//===-- 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 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 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 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 PrePruneTotalBlockSize; std::optional PostFixupTotalBlockSize; std::optional> 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 Lock(M); if (PrePruneTotalBlockSize) *PrePruneTotalBlockSize += computeTotalBlockSizes(G); return Error::success(); } Error StatsPlugin::recordPostFixupStats(LinkGraph &G) { std::lock_guard Lock(M); if (PostFixupTotalBlockSize) *PostFixupTotalBlockSize += computeTotalBlockSizes(G); return Error::success(); } namespace llvm { void enableStatistics(Session &S, bool UsingOrcRuntime) { StatsPlugin::enableIfNeeded(S, UsingOrcRuntime); } } // namespace llvm