1*9880d681SAndroid Build Coastguard Worker //===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker 10*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_SUPPORT_TIMER_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_SUPPORT_TIMER_H 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringRef.h" 14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/DataTypes.h" 15*9880d681SAndroid Build Coastguard Worker #include <cassert> 16*9880d681SAndroid Build Coastguard Worker #include <string> 17*9880d681SAndroid Build Coastguard Worker #include <utility> 18*9880d681SAndroid Build Coastguard Worker #include <vector> 19*9880d681SAndroid Build Coastguard Worker 20*9880d681SAndroid Build Coastguard Worker namespace llvm { 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard Worker class Timer; 23*9880d681SAndroid Build Coastguard Worker class TimerGroup; 24*9880d681SAndroid Build Coastguard Worker class raw_ostream; 25*9880d681SAndroid Build Coastguard Worker 26*9880d681SAndroid Build Coastguard Worker class TimeRecord { 27*9880d681SAndroid Build Coastguard Worker double WallTime; // Wall clock time elapsed in seconds 28*9880d681SAndroid Build Coastguard Worker double UserTime; // User time elapsed 29*9880d681SAndroid Build Coastguard Worker double SystemTime; // System time elapsed 30*9880d681SAndroid Build Coastguard Worker ssize_t MemUsed; // Memory allocated (in bytes) 31*9880d681SAndroid Build Coastguard Worker public: TimeRecord()32*9880d681SAndroid Build Coastguard Worker TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {} 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker /// getCurrentTime - Get the current time and memory usage. If Start is true 35*9880d681SAndroid Build Coastguard Worker /// we get the memory usage before the time, otherwise we get time before 36*9880d681SAndroid Build Coastguard Worker /// memory usage. This matters if the time to get the memory usage is 37*9880d681SAndroid Build Coastguard Worker /// significant and shouldn't be counted as part of a duration. 38*9880d681SAndroid Build Coastguard Worker static TimeRecord getCurrentTime(bool Start = true); 39*9880d681SAndroid Build Coastguard Worker getProcessTime()40*9880d681SAndroid Build Coastguard Worker double getProcessTime() const { return UserTime + SystemTime; } getUserTime()41*9880d681SAndroid Build Coastguard Worker double getUserTime() const { return UserTime; } getSystemTime()42*9880d681SAndroid Build Coastguard Worker double getSystemTime() const { return SystemTime; } getWallTime()43*9880d681SAndroid Build Coastguard Worker double getWallTime() const { return WallTime; } getMemUsed()44*9880d681SAndroid Build Coastguard Worker ssize_t getMemUsed() const { return MemUsed; } 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Worker // operator< - Allow sorting. 47*9880d681SAndroid Build Coastguard Worker bool operator<(const TimeRecord &T) const { 48*9880d681SAndroid Build Coastguard Worker // Sort by Wall Time elapsed, as it is the only thing really accurate 49*9880d681SAndroid Build Coastguard Worker return WallTime < T.WallTime; 50*9880d681SAndroid Build Coastguard Worker } 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Worker void operator+=(const TimeRecord &RHS) { 53*9880d681SAndroid Build Coastguard Worker WallTime += RHS.WallTime; 54*9880d681SAndroid Build Coastguard Worker UserTime += RHS.UserTime; 55*9880d681SAndroid Build Coastguard Worker SystemTime += RHS.SystemTime; 56*9880d681SAndroid Build Coastguard Worker MemUsed += RHS.MemUsed; 57*9880d681SAndroid Build Coastguard Worker } 58*9880d681SAndroid Build Coastguard Worker void operator-=(const TimeRecord &RHS) { 59*9880d681SAndroid Build Coastguard Worker WallTime -= RHS.WallTime; 60*9880d681SAndroid Build Coastguard Worker UserTime -= RHS.UserTime; 61*9880d681SAndroid Build Coastguard Worker SystemTime -= RHS.SystemTime; 62*9880d681SAndroid Build Coastguard Worker MemUsed -= RHS.MemUsed; 63*9880d681SAndroid Build Coastguard Worker } 64*9880d681SAndroid Build Coastguard Worker 65*9880d681SAndroid Build Coastguard Worker /// Print the current time record to \p OS, with a breakdown showing 66*9880d681SAndroid Build Coastguard Worker /// contributions to the \p Total time record. 67*9880d681SAndroid Build Coastguard Worker void print(const TimeRecord &Total, raw_ostream &OS) const; 68*9880d681SAndroid Build Coastguard Worker }; 69*9880d681SAndroid Build Coastguard Worker 70*9880d681SAndroid Build Coastguard Worker /// Timer - This class is used to track the amount of time spent between 71*9880d681SAndroid Build Coastguard Worker /// invocations of its startTimer()/stopTimer() methods. Given appropriate OS 72*9880d681SAndroid Build Coastguard Worker /// support it can also keep track of the RSS of the program at various points. 73*9880d681SAndroid Build Coastguard Worker /// By default, the Timer will print the amount of time it has captured to 74*9880d681SAndroid Build Coastguard Worker /// standard error when the last timer is destroyed, otherwise it is printed 75*9880d681SAndroid Build Coastguard Worker /// when its TimerGroup is destroyed. Timers do not print their information 76*9880d681SAndroid Build Coastguard Worker /// if they are never started. 77*9880d681SAndroid Build Coastguard Worker /// 78*9880d681SAndroid Build Coastguard Worker class Timer { 79*9880d681SAndroid Build Coastguard Worker TimeRecord Time; // The total time captured 80*9880d681SAndroid Build Coastguard Worker TimeRecord StartTime; // The time startTimer() was last called 81*9880d681SAndroid Build Coastguard Worker std::string Name; // The name of this time variable. 82*9880d681SAndroid Build Coastguard Worker bool Running; // Is the timer currently running? 83*9880d681SAndroid Build Coastguard Worker bool Triggered; // Has the timer ever been triggered? 84*9880d681SAndroid Build Coastguard Worker TimerGroup *TG; // The TimerGroup this Timer is in. 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker Timer **Prev, *Next; // Doubly linked list of timers in the group. 87*9880d681SAndroid Build Coastguard Worker public: Timer(StringRef N)88*9880d681SAndroid Build Coastguard Worker explicit Timer(StringRef N) : TG(nullptr) { init(N); } Timer(StringRef N,TimerGroup & tg)89*9880d681SAndroid Build Coastguard Worker Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); } Timer(const Timer & RHS)90*9880d681SAndroid Build Coastguard Worker Timer(const Timer &RHS) : TG(nullptr) { 91*9880d681SAndroid Build Coastguard Worker assert(!RHS.TG && "Can only copy uninitialized timers"); 92*9880d681SAndroid Build Coastguard Worker } 93*9880d681SAndroid Build Coastguard Worker const Timer &operator=(const Timer &T) { 94*9880d681SAndroid Build Coastguard Worker assert(!TG && !T.TG && "Can only assign uninit timers"); 95*9880d681SAndroid Build Coastguard Worker return *this; 96*9880d681SAndroid Build Coastguard Worker } 97*9880d681SAndroid Build Coastguard Worker ~Timer(); 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard Worker // Create an uninitialized timer, client must use 'init'. Timer()100*9880d681SAndroid Build Coastguard Worker explicit Timer() : TG(nullptr) {} 101*9880d681SAndroid Build Coastguard Worker void init(StringRef N); 102*9880d681SAndroid Build Coastguard Worker void init(StringRef N, TimerGroup &tg); 103*9880d681SAndroid Build Coastguard Worker getName()104*9880d681SAndroid Build Coastguard Worker const std::string &getName() const { return Name; } isInitialized()105*9880d681SAndroid Build Coastguard Worker bool isInitialized() const { return TG != nullptr; } 106*9880d681SAndroid Build Coastguard Worker 107*9880d681SAndroid Build Coastguard Worker /// Check if the timer is currently running. isRunning()108*9880d681SAndroid Build Coastguard Worker bool isRunning() const { return Running; } 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker /// Check if startTimer() has ever been called on this timer. hasTriggered()111*9880d681SAndroid Build Coastguard Worker bool hasTriggered() const { return Triggered; } 112*9880d681SAndroid Build Coastguard Worker 113*9880d681SAndroid Build Coastguard Worker /// Start the timer running. Time between calls to startTimer/stopTimer is 114*9880d681SAndroid Build Coastguard Worker /// counted by the Timer class. Note that these calls must be correctly 115*9880d681SAndroid Build Coastguard Worker /// paired. 116*9880d681SAndroid Build Coastguard Worker void startTimer(); 117*9880d681SAndroid Build Coastguard Worker 118*9880d681SAndroid Build Coastguard Worker /// Stop the timer. 119*9880d681SAndroid Build Coastguard Worker void stopTimer(); 120*9880d681SAndroid Build Coastguard Worker 121*9880d681SAndroid Build Coastguard Worker /// Clear the timer state. 122*9880d681SAndroid Build Coastguard Worker void clear(); 123*9880d681SAndroid Build Coastguard Worker 124*9880d681SAndroid Build Coastguard Worker /// Return the duration for which this timer has been running. getTotalTime()125*9880d681SAndroid Build Coastguard Worker TimeRecord getTotalTime() const { return Time; } 126*9880d681SAndroid Build Coastguard Worker 127*9880d681SAndroid Build Coastguard Worker private: 128*9880d681SAndroid Build Coastguard Worker friend class TimerGroup; 129*9880d681SAndroid Build Coastguard Worker }; 130*9880d681SAndroid Build Coastguard Worker 131*9880d681SAndroid Build Coastguard Worker /// The TimeRegion class is used as a helper class to call the startTimer() and 132*9880d681SAndroid Build Coastguard Worker /// stopTimer() methods of the Timer class. When the object is constructed, it 133*9880d681SAndroid Build Coastguard Worker /// starts the timer specified as its argument. When it is destroyed, it stops 134*9880d681SAndroid Build Coastguard Worker /// the relevant timer. This makes it easy to time a region of code. 135*9880d681SAndroid Build Coastguard Worker /// 136*9880d681SAndroid Build Coastguard Worker class TimeRegion { 137*9880d681SAndroid Build Coastguard Worker Timer *T; 138*9880d681SAndroid Build Coastguard Worker TimeRegion(const TimeRegion &) = delete; 139*9880d681SAndroid Build Coastguard Worker 140*9880d681SAndroid Build Coastguard Worker public: TimeRegion(Timer & t)141*9880d681SAndroid Build Coastguard Worker explicit TimeRegion(Timer &t) : T(&t) { 142*9880d681SAndroid Build Coastguard Worker T->startTimer(); 143*9880d681SAndroid Build Coastguard Worker } TimeRegion(Timer * t)144*9880d681SAndroid Build Coastguard Worker explicit TimeRegion(Timer *t) : T(t) { 145*9880d681SAndroid Build Coastguard Worker if (T) T->startTimer(); 146*9880d681SAndroid Build Coastguard Worker } ~TimeRegion()147*9880d681SAndroid Build Coastguard Worker ~TimeRegion() { 148*9880d681SAndroid Build Coastguard Worker if (T) T->stopTimer(); 149*9880d681SAndroid Build Coastguard Worker } 150*9880d681SAndroid Build Coastguard Worker }; 151*9880d681SAndroid Build Coastguard Worker 152*9880d681SAndroid Build Coastguard Worker /// NamedRegionTimer - This class is basically a combination of TimeRegion and 153*9880d681SAndroid Build Coastguard Worker /// Timer. It allows you to declare a new timer, AND specify the region to 154*9880d681SAndroid Build Coastguard Worker /// time, all in one statement. All timers with the same name are merged. This 155*9880d681SAndroid Build Coastguard Worker /// is primarily used for debugging and for hunting performance problems. 156*9880d681SAndroid Build Coastguard Worker /// 157*9880d681SAndroid Build Coastguard Worker struct NamedRegionTimer : public TimeRegion { 158*9880d681SAndroid Build Coastguard Worker explicit NamedRegionTimer(StringRef Name, 159*9880d681SAndroid Build Coastguard Worker bool Enabled = true); 160*9880d681SAndroid Build Coastguard Worker explicit NamedRegionTimer(StringRef Name, StringRef GroupName, 161*9880d681SAndroid Build Coastguard Worker bool Enabled = true); 162*9880d681SAndroid Build Coastguard Worker }; 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker /// The TimerGroup class is used to group together related timers into a single 165*9880d681SAndroid Build Coastguard Worker /// report that is printed when the TimerGroup is destroyed. It is illegal to 166*9880d681SAndroid Build Coastguard Worker /// destroy a TimerGroup object before all of the Timers in it are gone. A 167*9880d681SAndroid Build Coastguard Worker /// TimerGroup can be specified for a newly created timer in its constructor. 168*9880d681SAndroid Build Coastguard Worker /// 169*9880d681SAndroid Build Coastguard Worker class TimerGroup { 170*9880d681SAndroid Build Coastguard Worker std::string Name; 171*9880d681SAndroid Build Coastguard Worker Timer *FirstTimer; // First timer in the group. 172*9880d681SAndroid Build Coastguard Worker std::vector<std::pair<TimeRecord, std::string>> TimersToPrint; 173*9880d681SAndroid Build Coastguard Worker 174*9880d681SAndroid Build Coastguard Worker TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. 175*9880d681SAndroid Build Coastguard Worker TimerGroup(const TimerGroup &TG) = delete; 176*9880d681SAndroid Build Coastguard Worker void operator=(const TimerGroup &TG) = delete; 177*9880d681SAndroid Build Coastguard Worker 178*9880d681SAndroid Build Coastguard Worker public: 179*9880d681SAndroid Build Coastguard Worker explicit TimerGroup(StringRef name); 180*9880d681SAndroid Build Coastguard Worker ~TimerGroup(); 181*9880d681SAndroid Build Coastguard Worker setName(StringRef name)182*9880d681SAndroid Build Coastguard Worker void setName(StringRef name) { Name.assign(name.begin(), name.end()); } 183*9880d681SAndroid Build Coastguard Worker 184*9880d681SAndroid Build Coastguard Worker /// print - Print any started timers in this group and zero them. 185*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS); 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Worker /// printAll - This static method prints all timers and clears them all out. 188*9880d681SAndroid Build Coastguard Worker static void printAll(raw_ostream &OS); 189*9880d681SAndroid Build Coastguard Worker 190*9880d681SAndroid Build Coastguard Worker private: 191*9880d681SAndroid Build Coastguard Worker friend class Timer; 192*9880d681SAndroid Build Coastguard Worker void addTimer(Timer &T); 193*9880d681SAndroid Build Coastguard Worker void removeTimer(Timer &T); 194*9880d681SAndroid Build Coastguard Worker void PrintQueuedTimers(raw_ostream &OS); 195*9880d681SAndroid Build Coastguard Worker }; 196*9880d681SAndroid Build Coastguard Worker 197*9880d681SAndroid Build Coastguard Worker } // End llvm namespace 198*9880d681SAndroid Build Coastguard Worker 199*9880d681SAndroid Build Coastguard Worker #endif 200