//===--- Statistic.h - Helpers for llvm::Statistic --------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_BASIC_STATISTIC_H #define SWIFT_BASIC_STATISTIC_H #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "swift/Basic/SourceLoc.h" #include "swift/Basic/Timer.h" #define SWIFT_FUNC_STAT \ do { \ static llvm::Statistic FStat = \ {DEBUG_TYPE, __func__, __func__, {0}, false}; \ ++FStat; \ } while (0) // Helper class designed to consolidate reporting of LLVM statistics and timers // across swift compilations that typically invoke many drivers, each running // many frontends. Additionally collects some cheap "always-on" statistics, // beyond those that are (compile-time) parameterized by -DLLVM_ENABLE_STATS // (LLVM's stats are global and involve some amount of locking and mfences). // // Assumes it's given a process name and target name (the latter used as // decoration for its self-timer), and a directory to collect stats into, then: // // - On construction: // - Calls llvm::EnableStatistics(/*PrintOnExit=*/false) // - Calls swift::enableCompilationTimers() // - Starts an llvm::NamedRegionTimer for this process // // - On destruction: // - Add any standard always-enabled stats about the process as a whole // - Opens $dir/stats-$timestamp-$name-$random.json for writing // - Calls llvm::PrintStatisticsJSON(ostream) and/or its own writer // // Generally we make one of these per-process: either early in the life of the // driver, or early in the life of the frontend. namespace swift { class UnifiedStatsReporter { public: struct AlwaysOnDriverCounters { #define DRIVER_STATISTIC(ID) size_t ID; #include "Statistics.def" #undef DRIVER_STATISTIC }; struct AlwaysOnFrontendCounters { #define FRONTEND_STATISTIC(NAME, ID) size_t ID; #include "Statistics.def" #undef FRONTEND_STATISTIC }; struct AlwaysOnFrontendRecursiveSharedTimers { AlwaysOnFrontendRecursiveSharedTimers(); #define FRONTEND_RECURSIVE_SHARED_TIMER(ID) RecursiveSharedTimer ID; #include "Statistics.def" #undef FRONTEND_RECURSIVE_SHARED_TIMER int dummyInstanceVariableToGetConstructorToParse; }; struct FrontendStatsTracer { UnifiedStatsReporter *Reporter; llvm::TimeRecord SavedTime; StringRef Name; SourceRange Range; FrontendStatsTracer(StringRef Name, SourceRange const &Range, UnifiedStatsReporter *Reporter); FrontendStatsTracer(); FrontendStatsTracer(FrontendStatsTracer&& other); FrontendStatsTracer& operator=(FrontendStatsTracer&&); ~FrontendStatsTracer(); FrontendStatsTracer(const FrontendStatsTracer&) = delete; FrontendStatsTracer& operator=(const FrontendStatsTracer&) = delete; }; struct FrontendStatsEvent { uint64_t TimeUSec; uint64_t LiveUSec; bool IsEntry; StringRef EventName; StringRef CounterName; size_t CounterDelta; size_t CounterValue; SourceRange SourceRange; }; private: bool currentProcessExitStatusSet; int currentProcessExitStatus; SmallString<128> StatsFilename; SmallString<128> TraceFilename; llvm::TimeRecord StartedTime; std::unique_ptr Timer; SourceManager *SourceMgr; std::unique_ptr DriverCounters; std::unique_ptr FrontendCounters; std::unique_ptr LastTracedFrontendCounters; std::vector FrontendStatsEvents; std::unique_ptr FrontendRecursiveSharedTimers; void publishAlwaysOnStatsToLLVM(); void printAlwaysOnStatsAndTimers(llvm::raw_ostream &OS); UnifiedStatsReporter(StringRef ProgramName, StringRef AuxName, StringRef Directory, SourceManager *SM, bool TraceEvents); public: UnifiedStatsReporter(StringRef ProgramName, StringRef ModuleName, StringRef InputName, StringRef TripleName, StringRef OutputType, StringRef OptType, StringRef Directory, SourceManager *SM=nullptr, bool TraceEvents=false); ~UnifiedStatsReporter(); AlwaysOnDriverCounters &getDriverCounters(); AlwaysOnFrontendCounters &getFrontendCounters(); AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers(); void noteCurrentProcessExitStatus(int); FrontendStatsTracer getStatsTracer(StringRef N, SourceRange const &R); void saveAnyFrontendStatsEvents(FrontendStatsTracer const& T, bool IsEntry); }; } #endif // SWIFT_BASIC_STATISTIC_H