Line data Source code
1 : //===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_SUPPORT_TIMER_H
11 : #define LLVM_SUPPORT_TIMER_H
12 :
13 : #include "llvm/ADT/StringMap.h"
14 : #include "llvm/ADT/StringRef.h"
15 : #include "llvm/Support/DataTypes.h"
16 : #include <cassert>
17 : #include <string>
18 : #include <utility>
19 : #include <vector>
20 :
21 : namespace llvm {
22 :
23 : class Timer;
24 : class TimerGroup;
25 : class raw_ostream;
26 :
27 : class TimeRecord {
28 : double WallTime; ///< Wall clock time elapsed in seconds.
29 : double UserTime; ///< User time elapsed.
30 : double SystemTime; ///< System time elapsed.
31 : ssize_t MemUsed; ///< Memory allocated (in bytes).
32 : public:
33 43138 : TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
34 :
35 : /// Get the current time and memory usage. If Start is true we get the memory
36 : /// usage before the time, otherwise we get time before memory usage. This
37 : /// matters if the time to get the memory usage is significant and shouldn't
38 : /// be counted as part of a duration.
39 : static TimeRecord getCurrentTime(bool Start = true);
40 :
41 2617 : double getProcessTime() const { return UserTime + SystemTime; }
42 0 : double getUserTime() const { return UserTime; }
43 0 : double getSystemTime() const { return SystemTime; }
44 0 : double getWallTime() const { return WallTime; }
45 0 : ssize_t getMemUsed() const { return MemUsed; }
46 :
47 0 : bool operator<(const TimeRecord &T) const {
48 : // Sort by Wall Time elapsed, as it is the only thing really accurate
49 1 : return WallTime < T.WallTime;
50 : }
51 :
52 : void operator+=(const TimeRecord &RHS) {
53 5235 : WallTime += RHS.WallTime;
54 5235 : UserTime += RHS.UserTime;
55 5235 : SystemTime += RHS.SystemTime;
56 2406 : MemUsed += RHS.MemUsed;
57 : }
58 : void operator-=(const TimeRecord &RHS) {
59 2847 : WallTime -= RHS.WallTime;
60 2847 : UserTime -= RHS.UserTime;
61 2847 : SystemTime -= RHS.SystemTime;
62 2847 : MemUsed -= RHS.MemUsed;
63 : }
64 :
65 : /// Print the current time record to \p OS, with a breakdown showing
66 : /// contributions to the \p Total time record.
67 : void print(const TimeRecord &Total, raw_ostream &OS) const;
68 : };
69 :
70 : /// This class is used to track the amount of time spent between invocations of
71 : /// its startTimer()/stopTimer() methods. Given appropriate OS support it can
72 : /// also keep track of the RSS of the program at various points. By default,
73 : /// the Timer will print the amount of time it has captured to standard error
74 : /// when the last timer is destroyed, otherwise it is printed when its
75 : /// TimerGroup is destroyed. Timers do not print their information if they are
76 : /// never started.
77 : class Timer {
78 : TimeRecord Time; ///< The total time captured.
79 : TimeRecord StartTime; ///< The time startTimer() was last called.
80 : std::string Name; ///< The name of this time variable.
81 : std::string Description; ///< Description of this time variable.
82 : bool Running; ///< Is the timer currently running?
83 : bool Triggered; ///< Has the timer ever been triggered?
84 : TimerGroup *TG = nullptr; ///< The TimerGroup this Timer is in.
85 :
86 : Timer **Prev; ///< Pointer to \p Next of previous timer in group.
87 : Timer *Next; ///< Next timer in the group.
88 : public:
89 29527 : explicit Timer(StringRef Name, StringRef Description) {
90 29527 : init(Name, Description);
91 29527 : }
92 1361 : Timer(StringRef Name, StringRef Description, TimerGroup &tg) {
93 1361 : init(Name, Description, tg);
94 1361 : }
95 : Timer(const Timer &RHS) {
96 : assert(!RHS.TG && "Can only copy uninitialized timers");
97 : }
98 : const Timer &operator=(const Timer &T) {
99 : assert(!TG && !T.TG && "Can only assign uninit timers");
100 : return *this;
101 : }
102 : ~Timer();
103 :
104 : /// Create an uninitialized timer, client must use 'init'.
105 4192 : explicit Timer() {}
106 : void init(StringRef Name, StringRef Description);
107 : void init(StringRef Name, StringRef Description, TimerGroup &tg);
108 :
109 : const std::string &getName() const { return Name; }
110 : const std::string &getDescription() const { return Description; }
111 1 : bool isInitialized() const { return TG != nullptr; }
112 :
113 : /// Check if the timer is currently running.
114 0 : bool isRunning() const { return Running; }
115 :
116 : /// Check if startTimer() has ever been called on this timer.
117 0 : bool hasTriggered() const { return Triggered; }
118 :
119 : /// Start the timer running. Time between calls to startTimer/stopTimer is
120 : /// counted by the Timer class. Note that these calls must be correctly
121 : /// paired.
122 : void startTimer();
123 :
124 : /// Stop the timer.
125 : void stopTimer();
126 :
127 : /// Clear the timer state.
128 : void clear();
129 :
130 : /// Return the duration for which this timer has been running.
131 2 : TimeRecord getTotalTime() const { return Time; }
132 :
133 : private:
134 : friend class TimerGroup;
135 : };
136 :
137 : /// The TimeRegion class is used as a helper class to call the startTimer() and
138 : /// stopTimer() methods of the Timer class. When the object is constructed, it
139 : /// starts the timer specified as its argument. When it is destroyed, it stops
140 : /// the relevant timer. This makes it easy to time a region of code.
141 : class TimeRegion {
142 : Timer *T;
143 : TimeRegion(const TimeRegion &) = delete;
144 :
145 : public:
146 : explicit TimeRegion(Timer &t) : T(&t) {
147 14 : T->startTimer();
148 : }
149 23370113 : explicit TimeRegion(Timer *t) : T(t) {
150 101532676 : if (T) T->startTimer();
151 : }
152 : ~TimeRegion() {
153 124919063 : if (T) T->stopTimer();
154 : }
155 : };
156 :
157 : /// This class is basically a combination of TimeRegion and Timer. It allows
158 : /// you to declare a new timer, AND specify the region to time, all in one
159 : /// statement. All timers with the same name are merged. This is primarily
160 : /// used for debugging and for hunting performance problems.
161 : struct NamedRegionTimer : public TimeRegion {
162 : explicit NamedRegionTimer(StringRef Name, StringRef Description,
163 : StringRef GroupName,
164 : StringRef GroupDescription, bool Enabled = true);
165 : };
166 :
167 : /// The TimerGroup class is used to group together related timers into a single
168 : /// report that is printed when the TimerGroup is destroyed. It is illegal to
169 : /// destroy a TimerGroup object before all of the Timers in it are gone. A
170 : /// TimerGroup can be specified for a newly created timer in its constructor.
171 : class TimerGroup {
172 : struct PrintRecord {
173 : TimeRecord Time;
174 : std::string Name;
175 : std::string Description;
176 :
177 6417 : PrintRecord(const PrintRecord &Other) = default;
178 2408 : PrintRecord(const TimeRecord &Time, const std::string &Name,
179 : const std::string &Description)
180 2408 : : Time(Time), Name(Name), Description(Description) {}
181 :
182 : bool operator <(const PrintRecord &Other) const {
183 18828 : return Time < Other.Time;
184 : }
185 : };
186 : std::string Name;
187 : std::string Description;
188 : Timer *FirstTimer = nullptr; ///< First timer in the group.
189 : std::vector<PrintRecord> TimersToPrint;
190 :
191 : TimerGroup **Prev; ///< Pointer to Next field of previous timergroup in list.
192 : TimerGroup *Next; ///< Pointer to next timergroup in list.
193 : TimerGroup(const TimerGroup &TG) = delete;
194 : void operator=(const TimerGroup &TG) = delete;
195 :
196 : public:
197 : explicit TimerGroup(StringRef Name, StringRef Description);
198 :
199 : explicit TimerGroup(StringRef Name, StringRef Description,
200 : const StringMap<TimeRecord> &Records);
201 :
202 : ~TimerGroup();
203 :
204 : void setName(StringRef NewName, StringRef NewDescription) {
205 : Name.assign(NewName.begin(), NewName.end());
206 : Description.assign(NewDescription.begin(), NewDescription.end());
207 : }
208 :
209 : /// Print any started timers in this group.
210 : void print(raw_ostream &OS);
211 :
212 : /// Clear all timers in this group.
213 : void clear();
214 :
215 : /// This static method prints all timers.
216 : static void printAll(raw_ostream &OS);
217 :
218 : /// Clear out all timers. This is mostly used to disable automatic
219 : /// printing on shutdown, when timers have already been printed explicitly
220 : /// using \c printAll or \c printJSONValues.
221 : static void clearAll();
222 :
223 : const char *printJSONValues(raw_ostream &OS, const char *delim);
224 :
225 : /// Prints all timers as JSON key/value pairs.
226 : static const char *printAllJSONValues(raw_ostream &OS, const char *delim);
227 :
228 : /// Ensure global timer group lists are initialized. This function is mostly
229 : /// used by the Statistic code to influence the construction and destruction
230 : /// order of the global timer lists.
231 : static void ConstructTimerLists();
232 : private:
233 : friend class Timer;
234 : friend void PrintStatisticsJSON(raw_ostream &OS);
235 : void addTimer(Timer &T);
236 : void removeTimer(Timer &T);
237 : void prepareToPrintList();
238 : void PrintQueuedTimers(raw_ostream &OS);
239 : void printJSONValue(raw_ostream &OS, const PrintRecord &R,
240 : const char *suffix, double Value);
241 : };
242 :
243 : } // end namespace llvm
244 :
245 : #endif
|