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