1e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
2e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//
3e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//                     The LLVM Compiler Infrastructure
4e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//
5e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao// This file is distributed under the University of Illinois Open Source
6e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao// License. See LICENSE.TXT for details.
7e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//
8e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//===----------------------------------------------------------------------===//
9e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//
10e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao// This file defines three classes: Timer, TimeRegion, and TimerGroup,
11e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao// documented below.
12e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//
13e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao//===----------------------------------------------------------------------===//
14e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
15e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao#ifndef LLVM_SUPPORT_TIMER_H
16e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao#define LLVM_SUPPORT_TIMER_H
17e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DataTypes.h"
197abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include "llvm/ADT/StringRef.h"
207abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include <cassert>
21e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao#include <string>
22e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao#include <vector>
237abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao#include <utility>
24e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
25e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaonamespace llvm {
26e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
277abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoclass Timer;
28e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoclass TimerGroup;
29e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoclass raw_ostream;
30e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
317abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaoclass TimeRecord {
327abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double WallTime;       // Wall clock time elapsed in seconds
337abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double UserTime;       // User time elapsed
347abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double SystemTime;     // System time elapsed
357abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  ssize_t MemUsed;       // Memory allocated (in bytes)
367abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liaopublic:
377abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
387abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// getCurrentTime - Get the current time and memory usage.  If Start is true
407abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// we get the memory usage before the time, otherwise we get time before
417abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// memory usage.  This matters if the time to get the memory usage is
427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// significant and shouldn't be counted as part of a duration.
437abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  static TimeRecord getCurrentTime(bool Start = true);
447abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
457abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double getProcessTime() const { return UserTime+SystemTime; }
467abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double getUserTime() const { return UserTime; }
477abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double getSystemTime() const { return SystemTime; }
487abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  double getWallTime() const { return WallTime; }
497abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  ssize_t getMemUsed() const { return MemUsed; }
507abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
517abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
527abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // operator< - Allow sorting.
537abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  bool operator<(const TimeRecord &T) const {
547abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    // Sort by Wall Time elapsed, as it is the only thing really accurate
557abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    return WallTime < T.WallTime;
567abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
577abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
587abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void operator+=(const TimeRecord &RHS) {
597abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    WallTime   += RHS.WallTime;
607abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    UserTime   += RHS.UserTime;
617abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    SystemTime += RHS.SystemTime;
627abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    MemUsed    += RHS.MemUsed;
637abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
647abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void operator-=(const TimeRecord &RHS) {
657abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    WallTime   -= RHS.WallTime;
667abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    UserTime   -= RHS.UserTime;
677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    SystemTime -= RHS.SystemTime;
687abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    MemUsed    -= RHS.MemUsed;
697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// print - Print the current timer to standard error, and reset the "Started"
727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// flag.
737abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void print(const TimeRecord &Total, raw_ostream &OS) const;
747abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao};
757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
76e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// Timer - This class is used to track the amount of time spent between
77e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
78e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// support it can also keep track of the RSS of the program at various points.
79e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// By default, the Timer will print the amount of time it has captured to
80e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// standard error when the laster timer is destroyed, otherwise it is printed
81e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// when its TimerGroup is destroyed.  Timers do not print their information
82e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// if they are never started.
83e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao///
84e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoclass Timer {
857abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  TimeRecord Time;
867abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  std::string Name;      // The name of this time variable.
87e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  bool Started;          // Has this time variable ever been started?
88e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  TimerGroup *TG;        // The TimerGroup this Timer is in.
897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
907abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  Timer **Prev, *Next;   // Doubly linked list of timers in the group.
91e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaopublic:
927abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  explicit Timer(StringRef N) : TG(0) { init(N); }
937abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); }
947abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  Timer(const Timer &RHS) : TG(0) {
957abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    assert(RHS.TG == 0 && "Can only copy uninitialized timers");
967abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  }
97e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  const Timer &operator=(const Timer &T) {
987abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers");
99e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao    return *this;
100e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  }
1017abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  ~Timer();
102e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
1037abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  // Create an uninitialized timer, client must use 'init'.
1047abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  explicit Timer() : TG(0) {}
1057abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void init(StringRef N);
1067abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void init(StringRef N, TimerGroup &tg);
1077abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1087abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  const std::string &getName() const { return Name; }
1097abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  bool isInitialized() const { return TG != 0; }
1107abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
111e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  /// startTimer - Start the timer running.  Time between calls to
112e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
113e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  /// must be correctly paired.
114e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  ///
115e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  void startTimer();
116e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
117e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  /// stopTimer - Stop the timer.
118e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  ///
119e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  void stopTimer();
120e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
121e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoprivate:
122e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  friend class TimerGroup;
123e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao};
124e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
125e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
126e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// The TimeRegion class is used as a helper class to call the startTimer() and
127e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// stopTimer() methods of the Timer class.  When the object is constructed, it
128e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// starts the timer specified as it's argument.  When it is destroyed, it stops
129e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// the relevant timer.  This makes it easy to time a region of code.
130e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao///
131e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoclass TimeRegion {
132e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  Timer *T;
133e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT
134e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaopublic:
135e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  explicit TimeRegion(Timer &t) : T(&t) {
136e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao    T->startTimer();
137e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  }
138e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  explicit TimeRegion(Timer *t) : T(t) {
1397abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    if (T) T->startTimer();
140e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  }
141e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  ~TimeRegion() {
1427abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao    if (T) T->stopTimer();
143e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  }
144e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao};
145e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
146e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
147e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// NamedRegionTimer - This class is basically a combination of TimeRegion and
148e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// Timer.  It allows you to declare a new timer, AND specify the region to
149e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// time, all in one statement.  All timers with the same name are merged.  This
150e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// is primarily used for debugging and for hunting performance problems.
151e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao///
152e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaostruct NamedRegionTimer : public TimeRegion {
153e2a9508b0f0ac87d802ef01aa8038846c2ef7976Dan Gohman  explicit NamedRegionTimer(StringRef Name,
154e2a9508b0f0ac87d802ef01aa8038846c2ef7976Dan Gohman                            bool Enabled = true);
155e2a9508b0f0ac87d802ef01aa8038846c2ef7976Dan Gohman  explicit NamedRegionTimer(StringRef Name, StringRef GroupName,
156e2a9508b0f0ac87d802ef01aa8038846c2ef7976Dan Gohman                            bool Enabled = true);
157e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao};
158e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
159e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
160e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// The TimerGroup class is used to group together related timers into a single
161e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// report that is printed when the TimerGroup is destroyed.  It is illegal to
162e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// destroy a TimerGroup object before all of the Timers in it are gone.  A
163e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao/// TimerGroup can be specified for a newly created timer in its constructor.
164e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao///
165e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoclass TimerGroup {
166e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  std::string Name;
1677abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  Timer *FirstTimer;   // First timer in the group.
1686481ac152c1539eed76febde6e4b9b340ae674a4Shih-wei Liao  std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
1697abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1707abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
1717abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  TimerGroup(const TimerGroup &TG);      // DO NOT IMPLEMENT
1727abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void operator=(const TimerGroup &TG);  // DO NOT IMPLEMENT
173e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaopublic:
1747abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  explicit TimerGroup(StringRef name);
1757abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  ~TimerGroup();
1767abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1777abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
178e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
1797abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// print - Print any started timers in this group and zero them.
1807abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void print(raw_ostream &OS);
1817abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
1827abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  /// printAll - This static method prints all timers and clears them all out.
1837abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  static void printAll(raw_ostream &OS);
1847abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao
185e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liaoprivate:
186e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao  friend class Timer;
1877abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void addTimer(Timer &T);
1887abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void removeTimer(Timer &T);
1897abe37e4aee38cc79d91dd069a37d7e91d5bef53Shih-wei Liao  void PrintQueuedTimers(raw_ostream &OS);
190e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao};
191e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
192e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao} // End llvm namespace
193e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao
194e264f62ca09a8f65c87a46d562a4d0f9ec5d457Shih-wei Liao#endif
195