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