xref: /aosp_15_r20/external/llvm/include/llvm/Support/Timer.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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