Timer.h revision 198090
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
18193323Sed#include "llvm/Support/DataTypes.h"
19195098Sed#include "llvm/System/Mutex.h"
20193323Sed#include <string>
21193323Sed#include <vector>
22193323Sed#include <cassert>
23193323Sed
24193323Sednamespace llvm {
25193323Sed
26193323Sedclass TimerGroup;
27198090Srdivackyclass raw_ostream;
28193323Sed
29193323Sed/// Timer - This class is used to track the amount of time spent between
30198090Srdivacky/// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
31193323Sed/// support it can also keep track of the RSS of the program at various points.
32193323Sed/// By default, the Timer will print the amount of time it has captured to
33193323Sed/// standard error when the laster timer is destroyed, otherwise it is printed
34193323Sed/// when its TimerGroup is destroyed.  Timers do not print their information
35193323Sed/// if they are never started.
36193323Sed///
37193323Sedclass Timer {
38195098Sed  double Elapsed;        // Wall clock time elapsed in seconds
39195098Sed  double UserTime;       // User time elapsed
40195098Sed  double SystemTime;     // System time elapsed
41195098Sed  ssize_t MemUsed;       // Memory allocated (in bytes)
42195098Sed  size_t PeakMem;        // Peak memory used
43195098Sed  size_t PeakMemBase;    // Temporary for peak calculation...
44193323Sed  std::string Name;      // The name of this time variable
45193323Sed  bool Started;          // Has this time variable ever been started?
46193323Sed  TimerGroup *TG;        // The TimerGroup this Timer is in.
47195098Sed  mutable sys::SmartMutex<true> Lock; // Mutex for the contents of this Timer.
48193323Sedpublic:
49193323Sed  explicit Timer(const std::string &N);
50193323Sed  Timer(const std::string &N, TimerGroup &tg);
51193323Sed  Timer(const Timer &T);
52193323Sed  ~Timer();
53193323Sed
54195098Sed  double getProcessTime() const { return UserTime+SystemTime; }
55195098Sed  double getWallTime() const { return Elapsed; }
56195098Sed  ssize_t getMemUsed() const { return MemUsed; }
57195098Sed  size_t getPeakMem() const { return PeakMem; }
58193323Sed  std::string getName() const { return Name; }
59193323Sed
60193323Sed  const Timer &operator=(const Timer &T) {
61195098Sed    if (&T < this) {
62195098Sed      T.Lock.acquire();
63195098Sed      Lock.acquire();
64195098Sed    } else {
65195098Sed      Lock.acquire();
66195098Sed      T.Lock.acquire();
67195098Sed    }
68195098Sed
69193323Sed    Elapsed = T.Elapsed;
70193323Sed    UserTime = T.UserTime;
71193323Sed    SystemTime = T.SystemTime;
72193323Sed    MemUsed = T.MemUsed;
73193323Sed    PeakMem = T.PeakMem;
74193323Sed    PeakMemBase = T.PeakMemBase;
75193323Sed    Name = T.Name;
76193323Sed    Started = T.Started;
77193323Sed    assert(TG == T.TG && "Can only assign timers in the same TimerGroup!");
78195098Sed
79195098Sed    if (&T < this) {
80195098Sed      T.Lock.release();
81195098Sed      Lock.release();
82195098Sed    } else {
83195098Sed      Lock.release();
84195098Sed      T.Lock.release();
85195098Sed    }
86195098Sed
87193323Sed    return *this;
88193323Sed  }
89193323Sed
90193323Sed  // operator< - Allow sorting...
91193323Sed  bool operator<(const Timer &T) const {
92193323Sed    // Sort by Wall Time elapsed, as it is the only thing really accurate
93193323Sed    return Elapsed < T.Elapsed;
94193323Sed  }
95193323Sed  bool operator>(const Timer &T) const { return T.operator<(*this); }
96193323Sed
97193323Sed  /// startTimer - Start the timer running.  Time between calls to
98193323Sed  /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
99193323Sed  /// must be correctly paired.
100193323Sed  ///
101193323Sed  void startTimer();
102193323Sed
103193323Sed  /// stopTimer - Stop the timer.
104193323Sed  ///
105193323Sed  void stopTimer();
106193323Sed
107193323Sed  /// addPeakMemoryMeasurement - This method should be called whenever memory
108193323Sed  /// usage needs to be checked.  It adds a peak memory measurement to the
109193323Sed  /// currently active timers, which will be printed when the timer group prints
110193323Sed  ///
111193323Sed  static void addPeakMemoryMeasurement();
112193323Sed
113193323Sed  /// print - Print the current timer to standard error, and reset the "Started"
114193323Sed  /// flag.
115198090Srdivacky  void print(const Timer &Total, raw_ostream &OS);
116193323Sed
117193323Sedprivate:
118193323Sed  friend class TimerGroup;
119193323Sed
120193323Sed  // Copy ctor, initialize with no TG member.
121193323Sed  Timer(bool, const Timer &T);
122193323Sed
123193323Sed  /// sum - Add the time accumulated in the specified timer into this timer.
124193323Sed  ///
125193323Sed  void sum(const Timer &T);
126193323Sed};
127193323Sed
128193323Sed
129193323Sed/// The TimeRegion class is used as a helper class to call the startTimer() and
130193323Sed/// stopTimer() methods of the Timer class.  When the object is constructed, it
131193323Sed/// starts the timer specified as it's argument.  When it is destroyed, it stops
132193323Sed/// the relevant timer.  This makes it easy to time a region of code.
133193323Sed///
134193323Sedclass TimeRegion {
135193323Sed  Timer *T;
136193323Sed  TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT
137193323Sedpublic:
138193323Sed  explicit TimeRegion(Timer &t) : T(&t) {
139193323Sed    T->startTimer();
140193323Sed  }
141193323Sed  explicit TimeRegion(Timer *t) : T(t) {
142193323Sed    if (T)
143193323Sed      T->startTimer();
144193323Sed  }
145193323Sed  ~TimeRegion() {
146193323Sed    if (T)
147193323Sed      T->stopTimer();
148193323Sed  }
149193323Sed};
150193323Sed
151193323Sed
152193323Sed/// NamedRegionTimer - This class is basically a combination of TimeRegion and
153193323Sed/// Timer.  It allows you to declare a new timer, AND specify the region to
154193323Sed/// time, all in one statement.  All timers with the same name are merged.  This
155193323Sed/// is primarily used for debugging and for hunting performance problems.
156193323Sed///
157193323Sedstruct NamedRegionTimer : public TimeRegion {
158193323Sed  explicit NamedRegionTimer(const std::string &Name);
159193323Sed  explicit NamedRegionTimer(const std::string &Name,
160193323Sed                            const std::string &GroupName);
161193323Sed};
162193323Sed
163193323Sed
164193323Sed/// The TimerGroup class is used to group together related timers into a single
165193323Sed/// report that is printed when the TimerGroup is destroyed.  It is illegal to
166193323Sed/// destroy a TimerGroup object before all of the Timers in it are gone.  A
167193323Sed/// TimerGroup can be specified for a newly created timer in its constructor.
168193323Sed///
169193323Sedclass TimerGroup {
170193323Sed  std::string Name;
171193323Sed  unsigned NumTimers;
172193323Sed  std::vector<Timer> TimersToPrint;
173193323Sedpublic:
174193323Sed  explicit TimerGroup(const std::string &name) : Name(name), NumTimers(0) {}
175193323Sed  ~TimerGroup() {
176193323Sed    assert(NumTimers == 0 &&
177193323Sed           "TimerGroup destroyed before all contained timers!");
178193323Sed  }
179193323Sed
180193323Sedprivate:
181193323Sed  friend class Timer;
182195098Sed  void addTimer();
183193323Sed  void removeTimer();
184195098Sed  void addTimerToPrint(const Timer &T);
185193323Sed};
186193323Sed
187193323Sed} // End llvm namespace
188193323Sed
189193323Sed#endif
190