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