16c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===-- Timer.cpp - Interval Timing Support -------------------------------===// 2f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman// 8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===// 96c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// 106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// Interval Timing implementation. 116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// 126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===// 136c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 14551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Timer.h" 15551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 16fc86c3cfd6e81113722f17bebc54bc0b63389b58Chris Lattner#include "llvm/Support/Debug.h" 1790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner#include "llvm/Support/ManagedStatic.h" 18d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/raw_ostream.h" 19d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/Format.h" 201f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h" 211f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Process.h" 22ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner#include "llvm/ADT/OwningPtr.h" 23a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner#include "llvm/ADT/StringMap.h" 24b6d465f8131f5fb0b8e565685fb3395ed9aecbdbChris Lattnerusing namespace llvm; 25f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner 2649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on. 2749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnernamespace llvm { extern raw_ostream *CreateInfoOutputFile(); } 28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 2971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy 3071336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// of constructor/destructor ordering being unspecified by C++. Basically the 31ac0b6ae358944ae8b2b5a11dc08f52c3ed89f2daChris Lattner// problem is that a Statistic object gets destroyed, which ends up calling 3271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// 'GetLibSupportInfoOutputFile()' (below), which calls this function. 3371336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// LibSupportInfoOutputFilename used to be a global variable, but sometimes it 34f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// would get destroyed before the Statistic, causing havoc to ensue. We "fix" 35f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// this by creating the string the first time it is needed and never destroying 36f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// it. 3790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::string> LibSupportInfoOutputFilename; 3871336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattnerstatic std::string &getLibSupportInfoOutputFilename() { 39f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer return *LibSupportInfoOutputFilename; 4071336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner} 416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 4246d9a6494496d215e850f337b5a723c484212f80Owen Andersonstatic ManagedStatic<sys::SmartMutex<true> > TimerLock; 4346d9a6494496d215e850f337b5a723c484212f80Owen Anderson 443f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattnernamespace { 453c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman static cl::opt<bool> 463f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner TrackSpace("track-memory", cl::desc("Enable -time-passes memory " 473f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner "tracking (this may be slow)"), 483f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner cl::Hidden); 49f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner 503c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman static cl::opt<std::string, true> 5196a54db5e763c19f556a1b54ad2956cc91b81cb8Chris Lattner InfoOutputFilename("info-output-file", cl::value_desc("filename"), 52f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner cl::desc("File to append -stats and -timer output to"), 5371336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); 543f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner} 553f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner 5649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on. 5749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnerraw_ostream *llvm::CreateInfoOutputFile() { 58cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner const std::string &OutputFilename = getLibSupportInfoOutputFilename(); 59cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner if (OutputFilename.empty()) 6049a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(2, false); // stderr. 61cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner if (OutputFilename == "-") 6249a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(1, false); // stdout. 63f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 6486026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // Append mode is used because the info output file is opened and closed 6586026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // each time -stats or -time-passes wants to print output to it. To 6686026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // compensate for this, the test-suite Makefiles have code to delete the 6786026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // info output file before running commands which write to it. 68f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner std::string Error; 69cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner raw_ostream *Result = new raw_fd_ostream(OutputFilename.c_str(), 70f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner Error, raw_fd_ostream::F_Append); 71f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner if (Error.empty()) 72f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner return Result; 73f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 74f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner errs() << "Error opening info-output-file '" 75cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner << OutputFilename << " for appending!\n"; 76f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner delete Result; 7749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(2, false); // stderr. 78f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner} 79f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 80f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 81200aa6d89b75d2a4f630b85a4a785ae7d18d16bbOwen Andersonstatic TimerGroup *DefaultTimerGroup = 0; 826c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() { 839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner TimerGroup *tmp = DefaultTimerGroup; 843b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson sys::MemoryFence(); 859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner if (tmp) return tmp; 869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner llvm_acquire_global_lock(); 889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner tmp = DefaultTimerGroup; 893b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson if (!tmp) { 909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); 919bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::MemoryFence(); 929bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner DefaultTimerGroup = tmp; 933b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson } 949bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner llvm_release_global_lock(); 95c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov 963b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson return tmp; 976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 986c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===// 1009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation 1019bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===// 1029bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 103cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N) { 104a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner assert(TG == 0 && "Timer already initialized"); 105cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Name.assign(N.begin(), N.end()); 106a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Started = false; 107a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TG = getDefaultTimerGroup(); 108b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->addTimer(*this); 1096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 111cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N, TimerGroup &tg) { 112a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner assert(TG == 0 && "Timer already initialized"); 113cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Name.assign(N.begin(), N.end()); 114a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Started = false; 115a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TG = &tg; 116b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->addTimer(*this); 1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1186c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1196c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() { 120ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TG) return; // Never initialized, or already cleared. 121b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->removeTimer(*this); 1226c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1236c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 124e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() { 125ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TrackSpace) return 0; 126ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner return sys::Process::GetMallocUsage(); 127aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer} 128aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer 129a782e75d487006cafffdc256b3c623307fee4dcfChris LattnerTimeRecord TimeRecord::getCurrentTime(bool Start) { 130df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer TimeRecord Result; 131ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::TimeValue now(0,0), user(0,0), sys(0,0); 132ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 1337d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer if (Start) { 134ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Result.MemUsed = getMemUsage(); 1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::Process::GetTimeUsage(now, user, sys); 1367d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer } else { 1379bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::Process::GetTimeUsage(now, user, sys); 138ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Result.MemUsed = getMemUsage(); 1397d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer } 1408f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 141a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; 1429bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; 143a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; 1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner return Result; 1456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 14790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers; 1488f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 1496c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() { 1506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner Started = true; 151153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman ActiveTimers->push_back(this); 152a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Time -= TimeRecord::getCurrentTime(true); 1536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1556c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() { 156a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Time += TimeRecord::getCurrentTime(false); 1578f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 15890aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner if (ActiveTimers->back() == this) { 15990aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner ActiveTimers->pop_back(); 1608f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner } else { 1618f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner std::vector<Timer*>::iterator I = 16290aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner std::find(ActiveTimers->begin(), ActiveTimers->end(), this); 16390aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner assert(I != ActiveTimers->end() && "stop but no startTimer?"); 16490aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner ActiveTimers->erase(I); 1658f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner } 1666c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1689bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) { 1690613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner if (Total < 1e-7) // Avoid dividing by zero. 1709bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner OS << " ----- "; 171962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer else 172962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total); 1739bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner} 1749bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 175a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const { 176a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getUserTime()) 177a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getUserTime(), Total.getUserTime(), OS); 178a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getSystemTime()) 179a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getSystemTime(), Total.getSystemTime(), OS); 1809bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner if (Total.getProcessTime()) 1819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner printVal(getProcessTime(), Total.getProcessTime(), OS); 182a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getWallTime(), Total.getWallTime(), OS); 1839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 1849bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner OS << " "; 1859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 186a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getMemUsed()) 1874eb73c59bcd1055e9a3f324d836ce3898fbb7c81Benjamin Kramer OS << format("%9" PRId64 " ", (int64_t)getMemUsed()); 1889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner} 1899bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 1909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 191d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===// 192d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner// NamedRegionTimer Implementation 193d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===// 194d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 195b35798347ea87b8b6d36155b211016a7769f01abDan Gohmannamespace { 196b35798347ea87b8b6d36155b211016a7769f01abDan Gohman 197a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<Timer> Name2TimerMap; 198ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 199ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerclass Name2PairMap { 200ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map; 201ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerpublic: 202ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner ~Name2PairMap() { 203ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator 204ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner I = Map.begin(), E = Map.end(); I != E; ++I) 205ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner delete I->second.first; 206ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 207ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 208cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Timer &get(StringRef Name, StringRef GroupName) { 209ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 210ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 211ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName]; 212ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 213ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!GroupEntry.first) 214ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner GroupEntry.first = new TimerGroup(GroupName); 215ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 216ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Timer &T = GroupEntry.second[Name]; 217ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!T.isInitialized()) 218ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T.init(Name, *GroupEntry.first); 219ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner return T; 220ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 221ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner}; 2225e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman 223b35798347ea87b8b6d36155b211016a7769f01abDan Gohman} 224b35798347ea87b8b6d36155b211016a7769f01abDan Gohman 225a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2TimerMap> NamedTimers; 226a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2PairMap> NamedGroupedTimers; 227d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 228cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnerstatic Timer &getNamedRegionTimer(StringRef Name) { 229a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::SmartScopedLock<true> L(*TimerLock); 230a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner 231a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Timer &T = (*NamedTimers)[Name]; 232a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (!T.isInitialized()) 233a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner T.init(Name); 234a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner return T; 235d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner} 236d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 23703c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, 23803c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman bool Enabled) 23903c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman : TimeRegion(!Enabled ? 0 : &getNamedRegionTimer(Name)) {} 240d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 24103c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName, 24203c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman bool Enabled) 24303c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman : TimeRegion(!Enabled ? 0 : &NamedGroupedTimers->get(Name, GroupName)) {} 2448f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 2456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===// 2466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// TimerGroup Implementation 2476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===// 2486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 24983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroupList - This is the global list of TimerGroups, maintained by the 25083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroup ctor/dtor and is protected by the TimerLock lock. 25183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnerstatic TimerGroup *TimerGroupList = 0; 25283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 253cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris LattnerTimerGroup::TimerGroup(StringRef name) 254cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner : Name(name.begin(), name.end()), FirstTimer(0) { 25583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 25683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner // Add the group to TimerGroupList. 25783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 25883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner if (TimerGroupList) 25983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TimerGroupList->Prev = &Next; 26083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Next = TimerGroupList; 26183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Prev = &TimerGroupList; 26283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TimerGroupList = this; 26383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner} 26483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 2659f9f6d19dd67926446fb89a7b2dc0bda6353645bChris LattnerTimerGroup::~TimerGroup() { 2669f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner // If the timer group is destroyed before the timers it owns, accumulate and 2679f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner // print the timing data. 2689f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner while (FirstTimer != 0) 2699f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner removeTimer(*FirstTimer); 27083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 27183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner // Remove the group from the TimerGroupList. 27283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 27383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner *Prev = Next; 27483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner if (Next) 27583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Next->Prev = Prev; 2769f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner} 2779f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 2789f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 279b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::removeTimer(Timer &T) { 280a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::SmartScopedLock<true> L(*TimerLock); 2819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 282b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // If the timer was started, move its data to TimersToPrint. 2839f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner if (T.Started) 284b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TimersToPrint.push_back(std::make_pair(T.Time, T.Name)); 2859f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 2869f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner T.TG = 0; 287b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 288b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Unlink the timer from our list. 289b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner *T.Prev = T.Next; 290b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (T.Next) 291b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Next->Prev = T.Prev; 292b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 293b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Print the report when all timers in this group are destroyed if some of 294b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // them were started. 295b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (FirstTimer != 0 || TimersToPrint.empty()) 296b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner return; 297b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 29849a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner raw_ostream *OutStream = CreateInfoOutputFile(); 299b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner PrintQueuedTimers(*OutStream); 30049a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner delete OutStream; // Close the file. 301b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner} 302b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 303b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::addTimer(Timer &T) { 304b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 305b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 306b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Add the timer to our list. 307b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (FirstTimer) 308b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner FirstTimer->Prev = &T.Next; 309b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Next = FirstTimer; 310b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Prev = &FirstTimer; 311b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner FirstTimer = &T; 312b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner} 3139bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 314b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::PrintQueuedTimers(raw_ostream &OS) { 315b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Sort the timers in descending order by amount of time taken. 316fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer std::sort(TimersToPrint.begin(), TimersToPrint.end()); 317fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer 318a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TimeRecord Total; 319a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) 320a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Total += TimersToPrint[i].first; 321b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 322a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Print out timing header. 323b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "===" << std::string(73, '-') << "===\n"; 324b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Figure out how many spaces to indent TimerGroup name. 325b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner unsigned Padding = (80-Name.length())/2; 326b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (Padding > 80) Padding = 0; // Don't allow "negative" numbers 327b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS.indent(Padding) << Name << '\n'; 328b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "===" << std::string(73, '-') << "===\n"; 329b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 330a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // If this is not an collection of ungrouped times, print the total time. 331a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Ungrouped timers don't really make sense to add up. We still print the 332a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // TOTAL line to make the percentages make sense. 333962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer if (this != DefaultTimerGroup) 334962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n", 335962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer Total.getProcessTime(), Total.getWallTime()); 336b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << '\n'; 337b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 338a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getUserTime()) 339b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---User Time---"; 340a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getSystemTime()) 341b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --System Time--"; 342a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getProcessTime()) 343b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --User+System--"; 344b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---Wall Time---"; 345a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getMemUsed()) 346b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---Mem---"; 347b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --- Name ---\n"; 348b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 349a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Loop through all of the timing data, printing it out. 350a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) { 351a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1]; 352b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner Entry.first.print(Total, OS); 353b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << Entry.second << '\n'; 354a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner } 355b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 356b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner Total.print(Total, OS); 357b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "Total\n\n"; 358b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS.flush(); 359b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 3609bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner TimersToPrint.clear(); 36146d9a6494496d215e850f337b5a723c484212f80Owen Anderson} 36246d9a6494496d215e850f337b5a723c484212f80Owen Anderson 363ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner/// print - Print any started timers in this group and zero them. 364ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnervoid TimerGroup::print(raw_ostream &OS) { 365ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 366ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 367ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // See if any of our timers were started, if so add them to TimersToPrint and 368ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // reset them. 369ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner for (Timer *T = FirstTimer; T; T = T->Next) { 370ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!T->Started) continue; 371ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner TimersToPrint.push_back(std::make_pair(T->Time, T->Name)); 372ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 373ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // Clear out the time. 374ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T->Started = 0; 375ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T->Time = TimeRecord(); 376ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 377ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 378ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // If any timers were started, print the group. 379ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TimersToPrint.empty()) 380ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner PrintQueuedTimers(OS); 381ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner} 38283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 38383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// printAll - This static method prints all timers and clears them all out. 38483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnervoid TimerGroup::printAll(raw_ostream &OS) { 38583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 38683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 38783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) 38883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TG->print(OS); 38983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner} 390