Timer.h revision 206083
1193323Sed//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines three classes: Timer, TimeRegion, and TimerGroup,
11193323Sed// documented below.
12193323Sed//
13193323Sed//===----------------------------------------------------------------------===//
14193323Sed
15193323Sed#ifndef LLVM_SUPPORT_TIMER_H
16193323Sed#define LLVM_SUPPORT_TIMER_H
17193323Sed
18198892Srdivacky#include "llvm/System/DataTypes.h"
19206083Srdivacky#include "llvm/ADT/StringRef.h"
20206083Srdivacky#include <cassert>
21193323Sed#include <string>
22193323Sed#include <vector>
23206083Srdivacky#include <utility>
24193323Sed
25193323Sednamespace llvm {
26193323Sed
27206083Srdivackyclass Timer;
28193323Sedclass TimerGroup;
29198090Srdivackyclass raw_ostream;
30193323Sed
31206083Srdivackyclass TimeRecord {
32206083Srdivacky  double WallTime;       // Wall clock time elapsed in seconds
33206083Srdivacky  double UserTime;       // User time elapsed
34206083Srdivacky  double SystemTime;     // System time elapsed
35206083Srdivacky  ssize_t MemUsed;       // Memory allocated (in bytes)
36206083Srdivackypublic:
37206083Srdivacky  TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
38206083Srdivacky
39206083Srdivacky  /// getCurrentTime - Get the current time and memory usage.  If Start is true
40206083Srdivacky  /// we get the memory usage before the time, otherwise we get time before
41206083Srdivacky  /// memory usage.  This matters if the time to get the memory usage is
42206083Srdivacky  /// significant and shouldn't be counted as part of a duration.
43206083Srdivacky  static TimeRecord getCurrentTime(bool Start = true);
44206083Srdivacky
45206083Srdivacky  double getProcessTime() const { return UserTime+SystemTime; }
46206083Srdivacky  double getUserTime() const { return UserTime; }
47206083Srdivacky  double getSystemTime() const { return SystemTime; }
48206083Srdivacky  double getWallTime() const { return WallTime; }
49206083Srdivacky  ssize_t getMemUsed() const { return MemUsed; }
50206083Srdivacky
51206083Srdivacky
52206083Srdivacky  // operator< - Allow sorting.
53206083Srdivacky  bool operator<(const TimeRecord &T) const {
54206083Srdivacky    // Sort by Wall Time elapsed, as it is the only thing really accurate
55206083Srdivacky    return WallTime < T.WallTime;
56206083Srdivacky  }
57206083Srdivacky
58206083Srdivacky  void operator+=(const TimeRecord &RHS) {
59206083Srdivacky    WallTime   += RHS.WallTime;
60206083Srdivacky    UserTime   += RHS.UserTime;
61206083Srdivacky    SystemTime += RHS.SystemTime;
62206083Srdivacky    MemUsed    += RHS.MemUsed;
63206083Srdivacky  }
64206083Srdivacky  void operator-=(const TimeRecord &RHS) {
65206083Srdivacky    WallTime   -= RHS.WallTime;
66206083Srdivacky    UserTime   -= RHS.UserTime;
67206083Srdivacky    SystemTime -= RHS.SystemTime;
68206083Srdivacky    MemUsed    -= RHS.MemUsed;
69206083Srdivacky  }
70206083Srdivacky
71206083Srdivacky  /// print - Print the current timer to standard error, and reset the "Started"
72206083Srdivacky  /// flag.
73206083Srdivacky  void print(const TimeRecord &Total, raw_ostream &OS) const;
74206083Srdivacky};
75206083Srdivacky
76193323Sed/// Timer - This class is used to track the amount of time spent between
77198090Srdivacky/// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
78193323Sed/// support it can also keep track of the RSS of the program at various points.
79193323Sed/// By default, the Timer will print the amount of time it has captured to
80193323Sed/// standard error when the laster timer is destroyed, otherwise it is printed
81193323Sed/// when its TimerGroup is destroyed.  Timers do not print their information
82193323Sed/// if they are never started.
83193323Sed///
84193323Sedclass Timer {
85206083Srdivacky  TimeRecord Time;
86206083Srdivacky  std::string Name;      // The name of this time variable.
87193323Sed  bool Started;          // Has this time variable ever been started?
88193323Sed  TimerGroup *TG;        // The TimerGroup this Timer is in.
89206083Srdivacky
90206083Srdivacky  Timer **Prev, *Next;   // Doubly linked list of timers in the group.
91193323Sedpublic:
92206083Srdivacky  explicit Timer(StringRef N) : TG(0) { init(N); }
93206083Srdivacky  Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); }
94206083Srdivacky  Timer(const Timer &RHS) : TG(0) {
95206083Srdivacky    assert(RHS.TG == 0 && "Can only copy uninitialized timers");
96206083Srdivacky  }
97193323Sed  const Timer &operator=(const Timer &T) {
98206083Srdivacky    assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers");
99193323Sed    return *this;
100193323Sed  }
101206083Srdivacky  ~Timer();
102193323Sed
103206083Srdivacky  // Create an uninitialized timer, client must use 'init'.
104206083Srdivacky  explicit Timer() : TG(0) {}
105206083Srdivacky  void init(StringRef N);
106206083Srdivacky  void init(StringRef N, TimerGroup &tg);
107206083Srdivacky
108206083Srdivacky  const std::string &getName() const { return Name; }
109206083Srdivacky  bool isInitialized() const { return TG != 0; }
110206083Srdivacky
111193323Sed  /// startTimer - Start the timer running.  Time between calls to
112193323Sed  /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
113193323Sed  /// must be correctly paired.
114193323Sed  ///
115193323Sed  void startTimer();
116193323Sed
117193323Sed  /// stopTimer - Stop the timer.
118193323Sed  ///
119193323Sed  void stopTimer();
120193323Sed
121193323Sedprivate:
122193323Sed  friend class TimerGroup;
123193323Sed};
124193323Sed
125193323Sed
126193323Sed/// The TimeRegion class is used as a helper class to call the startTimer() and
127193323Sed/// stopTimer() methods of the Timer class.  When the object is constructed, it
128193323Sed/// starts the timer specified as it's argument.  When it is destroyed, it stops
129193323Sed/// the relevant timer.  This makes it easy to time a region of code.
130193323Sed///
131193323Sedclass TimeRegion {
132193323Sed  Timer *T;
133193323Sed  TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT
134193323Sedpublic:
135193323Sed  explicit TimeRegion(Timer &t) : T(&t) {
136193323Sed    T->startTimer();
137193323Sed  }
138193323Sed  explicit TimeRegion(Timer *t) : T(t) {
139206083Srdivacky    if (T) T->startTimer();
140193323Sed  }
141193323Sed  ~TimeRegion() {
142206083Srdivacky    if (T) T->stopTimer();
143193323Sed  }
144193323Sed};
145193323Sed
146193323Sed
147193323Sed/// NamedRegionTimer - This class is basically a combination of TimeRegion and
148193323Sed/// Timer.  It allows you to declare a new timer, AND specify the region to
149193323Sed/// time, all in one statement.  All timers with the same name are merged.  This
150193323Sed/// is primarily used for debugging and for hunting performance problems.
151193323Sed///
152193323Sedstruct NamedRegionTimer : public TimeRegion {
153206083Srdivacky  explicit NamedRegionTimer(StringRef Name);
154206083Srdivacky  explicit NamedRegionTimer(StringRef Name, StringRef GroupName);
155193323Sed};
156193323Sed
157193323Sed
158193323Sed/// The TimerGroup class is used to group together related timers into a single
159193323Sed/// report that is printed when the TimerGroup is destroyed.  It is illegal to
160193323Sed/// destroy a TimerGroup object before all of the Timers in it are gone.  A
161193323Sed/// TimerGroup can be specified for a newly created timer in its constructor.
162193323Sed///
163193323Sedclass TimerGroup {
164193323Sed  std::string Name;
165206083Srdivacky  Timer *FirstTimer;   // First timer in the group.
166206083Srdivacky  std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
167206083Srdivacky
168206083Srdivacky  TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
169206083Srdivacky  TimerGroup(const TimerGroup &TG);      // DO NOT IMPLEMENT
170206083Srdivacky  void operator=(const TimerGroup &TG);  // DO NOT IMPLEMENT
171193323Sedpublic:
172206083Srdivacky  explicit TimerGroup(StringRef name);
173206083Srdivacky  ~TimerGroup();
174193323Sed
175206083Srdivacky  void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
176206083Srdivacky
177206083Srdivacky  /// print - Print any started timers in this group and zero them.
178206083Srdivacky  void print(raw_ostream &OS);
179206083Srdivacky
180206083Srdivacky  /// printAll - This static method prints all timers and clears them all out.
181206083Srdivacky  static void printAll(raw_ostream &OS);
182206083Srdivacky
183193323Sedprivate:
184193323Sed  friend class Timer;
185206083Srdivacky  void addTimer(Timer &T);
186206083Srdivacky  void removeTimer(Timer &T);
187206083Srdivacky  void PrintQueuedTimers(raw_ostream &OS);
188193323Sed};
189193323Sed
190193323Sed} // End llvm namespace
191193323Sed
192193323Sed#endif
193