summaryrefslogtreecommitdiff
path: root/include/Support/Timer.h
blob: c36006f25d520f7c447c513c93ba030442631fd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//===-- Support/Timer.h - Interval Timing Support ---------------*- C++ -*-===//
//
// This file defines three classes: Timer, TimeRegion, and TimerGroup.
//
// The Timer class is used to track the amount of time spent between invocations
// of it's startTimer()/stopTimer() methods.  Given appropriate OS support it
// can also keep track of the RSS of the program at various points.  By default,
// the Timer will print the amount of time it has captured to standard error
// when the laster timer is destroyed, otherwise it is printed when it's
// TimerGroup is destroyed.  Timer's do not print their information if they are
// never started.
//
// The TimeRegion class is used as a helper class to call the startTimer() and
// stopTimer() methods of the Timer class.  When the object is constructed, it
// starts the timer specified as it's argument.  When it is destroyed, it stops
// the relevant timer.  This makes it easy to time a region of code.
//
// The TimerGroup class is used to group together related timers into a single
// report that is printed when the TimerGroup is destroyed.  It is illegal to
// destroy a TimerGroup object before all of the Timers in it are gone.  A
// TimerGroup can be specified for a newly created timer in its constructor.
//
//===----------------------------------------------------------------------===//

#ifndef SUPPORT_TIMER_H
#define SUPPORT_TIMER_H

#include <string>
#include <vector>
#include <iosfwd>

class TimerGroup;

class Timer {
  double Elapsed;        // Wall clock time elapsed in seconds
  double UserTime;       // User time elapsed
  double SystemTime;     // System time elapsed
  long   MemUsed;        // Memory allocated (in bytes)
  long   PeakMem;        // Peak memory used
  long   PeakMemBase;    // Temporary for peak calculation...
  std::string Name;      // The name of this time variable
  bool Started;          // Has this time variable ever been started?
  TimerGroup *TG;        // The TimerGroup this Timer is in.
public:
  Timer(const std::string &N);
  Timer(const std::string &N, TimerGroup &tg);
  Timer(const Timer &T);
  ~Timer();

  double getProcessTime() const { return UserTime+SystemTime; }
  double getWallTime() const { return Elapsed; }
  long getMemUsed() const { return MemUsed; }
  long getPeakMem() const { return PeakMem; }
  std::string   getName() const { return Name; }

  const Timer &operator=(const Timer &T) {
    Elapsed = T.Elapsed;
    UserTime = T.UserTime;
    SystemTime = T.SystemTime;
    MemUsed = T.MemUsed;
    PeakMem = T.PeakMem;
    PeakMemBase = T.PeakMemBase;
    Name = T.Name;
    Started = T.Started;
    assert(TG == T.TG && "Can only assign timers in the same TimerGroup!");
    return *this;
  }

  // operator< - Allow sorting...
  bool operator<(const Timer &T) const {
    // Sort by Wall Time elapsed, as it is the only thing really accurate
    return Elapsed < T.Elapsed;
  }
  bool operator>(const Timer &T) const { return T.operator<(*this); }
  
  /// startTimer - Start the timer running.  Time between calls to
  /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
  /// must be correctly paired.
  ///
  void startTimer();

  /// stopTimer - Stop the timer.
  ///
  void stopTimer();

  /// addPeakMemoryMeasurement - This method should be called whenever memory
  /// usage needs to be checked.  It adds a peak memory measurement to the
  /// currently active timers, which will be printed when the timer group prints
  ///
  static void addPeakMemoryMeasurement();

  /// print - Print the current timer to standard error, and reset the "Started"
  /// flag.
  void print(const Timer &Total, std::ostream &OS);

private:
  friend class TimerGroup;

  // Copy ctor, initialize with no TG member.
  Timer(bool, const Timer &T);

  /// sum - Add the time accumulated in the specified timer into this timer.
  ///
  void sum(const Timer &T);
};


class TimeRegion {
  Timer &T;
  TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT
public:
  TimeRegion(Timer &t) : T(t) {
    T.startTimer();
  }
  ~TimeRegion() {
    T.stopTimer();
  }
};

class TimerGroup {
  std::string Name;
  unsigned NumTimers;
  std::vector<Timer> TimersToPrint;
public:
  TimerGroup(const std::string &name) : Name(name), NumTimers(0) {}
  ~TimerGroup() {
    assert(NumTimers == 0 &&
           "TimerGroup destroyed before all contained timers!");
  }

private:
  friend class Timer;
  void addTimer() { ++NumTimers; }
  void removeTimer();
  void addTimerToPrint(const Timer &T) {
    TimersToPrint.push_back(Timer(true, T));
  }
};

#endif