1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===//
263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman//
3b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//                     The LLVM Compiler Infrastructure
4b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman//
8b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//===----------------------------------------------------------------------===//
96c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
10551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#ifndef LLVM_SUPPORT_TIMER_H
11551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#define LLVM_SUPPORT_TIMER_H
126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
13255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/ADT/StringRef.h"
14f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper#include "llvm/Support/Compiler.h"
151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DataTypes.h"
16a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner#include <cassert>
17fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer#include <string>
18a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner#include <utility>
19255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include <vector>
20be583b914d8156b99d3da264d5adca37fee8dbc9John Criswell
21d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekenamespace llvm {
22d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
23a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerclass Timer;
246c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerclass TimerGroup;
25d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattnerclass raw_ostream;
266c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
27a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerclass TimeRecord {
28a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double WallTime;       // Wall clock time elapsed in seconds
29a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double UserTime;       // User time elapsed
30a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double SystemTime;     // System time elapsed
31a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  ssize_t MemUsed;       // Memory allocated (in bytes)
32a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerpublic:
33a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {}
34a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
35a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// getCurrentTime - Get the current time and memory usage.  If Start is true
36a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// we get the memory usage before the time, otherwise we get time before
37a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// memory usage.  This matters if the time to get the memory usage is
38a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// significant and shouldn't be counted as part of a duration.
39a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  static TimeRecord getCurrentTime(bool Start = true);
40a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
41a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double getProcessTime() const { return UserTime+SystemTime; }
42a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double getUserTime() const { return UserTime; }
43a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double getSystemTime() const { return SystemTime; }
44a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  double getWallTime() const { return WallTime; }
45a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  ssize_t getMemUsed() const { return MemUsed; }
46a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
47a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
48a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // operator< - Allow sorting.
49a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  bool operator<(const TimeRecord &T) const {
50a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    // Sort by Wall Time elapsed, as it is the only thing really accurate
51a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    return WallTime < T.WallTime;
52a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
53a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
54a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  void operator+=(const TimeRecord &RHS) {
55a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    WallTime   += RHS.WallTime;
56a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    UserTime   += RHS.UserTime;
57a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    SystemTime += RHS.SystemTime;
58a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    MemUsed    += RHS.MemUsed;
59a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
60a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  void operator-=(const TimeRecord &RHS) {
61a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    WallTime   -= RHS.WallTime;
62a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    UserTime   -= RHS.UserTime;
63a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    SystemTime -= RHS.SystemTime;
64a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    MemUsed    -= RHS.MemUsed;
65a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
66a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
67a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// print - Print the current timer to standard error, and reset the "Started"
68a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  /// flag.
69a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  void print(const TimeRecord &Total, raw_ostream &OS) const;
70a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner};
71a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
72aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// Timer - This class is used to track the amount of time spent between
7375144f93eb7e4dbf22d308d21581ae255dd520c6Dan Gohman/// invocations of its startTimer()/stopTimer() methods.  Given appropriate OS
74aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// support it can also keep track of the RSS of the program at various points.
75aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// By default, the Timer will print the amount of time it has captured to
76b6080b48cfce5de877a90f34eba344afcf2f9f2cEli Bendersky/// standard error when the last timer is destroyed, otherwise it is printed
7794f9c7dc97bc586e01c101e9fcfeb93c2fb4bd87Dan Gohman/// when its TimerGroup is destroyed.  Timers do not print their information
78aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// if they are never started.
79aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner///
806c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerclass Timer {
81a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TimeRecord Time;
820ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  std::string Name;      // The name of this time variable.
836c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  bool Started;          // Has this time variable ever been started?
846c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TimerGroup *TG;        // The TimerGroup this Timer is in.
85b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
86b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  Timer **Prev, *Next;   // Doubly linked list of timers in the group.
876c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerpublic:
88cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  explicit Timer(StringRef N) : TG(0) { init(N); }
89cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); }
90a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Timer(const Timer &RHS) : TG(0) {
91a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    assert(RHS.TG == 0 && "Can only copy uninitialized timers");
92a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
93a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  const Timer &operator=(const Timer &T) {
94a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers");
95a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    return *this;
96a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  ~Timer();
986c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
99a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Create an uninitialized timer, client must use 'init'.
100a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  explicit Timer() : TG(0) {}
101cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  void init(StringRef N);
102cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  void init(StringRef N, TimerGroup &tg);
103a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
104a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  const std::string &getName() const { return Name; }
105a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  bool isInitialized() const { return TG != 0; }
1060ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner
1076c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  /// startTimer - Start the timer running.  Time between calls to
1086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  /// startTimer/stopTimer is counted by the Timer class.  Note that these calls
1096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  /// must be correctly paired.
1106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  ///
1116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  void startTimer();
1126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1136c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  /// stopTimer - Stop the timer.
1146c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  ///
1156c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  void stopTimer();
1166c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerprivate:
1186c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  friend class TimerGroup;
1196c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner};
1206c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
122aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// The TimeRegion class is used as a helper class to call the startTimer() and
123aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// stopTimer() methods of the Timer class.  When the object is constructed, it
124b6080b48cfce5de877a90f34eba344afcf2f9f2cEli Bendersky/// starts the timer specified as its argument.  When it is destroyed, it stops
125aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// the relevant timer.  This makes it easy to time a region of code.
126aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner///
1276c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerclass TimeRegion {
128ccd846b73ffce9296e392e550712926845098fabChris Lattner  Timer *T;
129f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper  TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION;
1306c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerpublic:
131ccd846b73ffce9296e392e550712926845098fabChris Lattner  explicit TimeRegion(Timer &t) : T(&t) {
132ccd846b73ffce9296e392e550712926845098fabChris Lattner    T->startTimer();
133ccd846b73ffce9296e392e550712926845098fabChris Lattner  }
134ccd846b73ffce9296e392e550712926845098fabChris Lattner  explicit TimeRegion(Timer *t) : T(t) {
135b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    if (T) T->startTimer();
1366c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
1376c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  ~TimeRegion() {
138b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    if (T) T->stopTimer();
1396c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
1406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner};
1416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
142aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner
143aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// NamedRegionTimer - This class is basically a combination of TimeRegion and
144aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// Timer.  It allows you to declare a new timer, AND specify the region to
145aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// time, all in one statement.  All timers with the same name are merged.  This
146aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// is primarily used for debugging and for hunting performance problems.
147aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner///
148aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattnerstruct NamedRegionTimer : public TimeRegion {
14903c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman  explicit NamedRegionTimer(StringRef Name,
15003c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                            bool Enabled = true);
15103c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman  explicit NamedRegionTimer(StringRef Name, StringRef GroupName,
15203c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                            bool Enabled = true);
153aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner};
154aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner
155aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner
156aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// The TimerGroup class is used to group together related timers into a single
157aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// report that is printed when the TimerGroup is destroyed.  It is illegal to
158aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// destroy a TimerGroup object before all of the Timers in it are gone.  A
159aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner/// TimerGroup can be specified for a newly created timer in its constructor.
160aacd3c8d86d6d4aa69ddae8814b4839a4973028aChris Lattner///
1616c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerclass TimerGroup {
1626c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  std::string Name;
163b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  Timer *FirstTimer;   // First timer in the group.
164fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer  std::vector<std::pair<TimeRecord, std::string> > TimersToPrint;
16583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
16683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's.
167f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper  TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
168f630e49efc7bf3f1716b6daab3c2cc11a908754aCraig Topper  void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION;
1696c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerpublic:
170cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  explicit TimerGroup(StringRef name);
1719f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  ~TimerGroup();
172b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
173cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  void setName(StringRef name) { Name.assign(name.begin(), name.end()); }
174ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
175ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  /// print - Print any started timers in this group and zero them.
176ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  void print(raw_ostream &OS);
177b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
17883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  /// printAll - This static method prints all timers and clears them all out.
17983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  static void printAll(raw_ostream &OS);
18083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
1816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerprivate:
1826c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  friend class Timer;
183b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  void addTimer(Timer &T);
184b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  void removeTimer(Timer &T);
185ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  void PrintQueuedTimers(raw_ostream &OS);
1866c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner};
1876c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
188d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace
189d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
1906c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner#endif
191