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