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