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" 15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/StringMap.h" 16551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h" 17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/FileSystem.h" 18d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/Format.h" 19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ManagedStatic.h" 201f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h" 211f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Process.h" 22d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/raw_ostream.h" 23b6d465f8131f5fb0b8e565685fb3395ed9aecbdbChris Lattnerusing namespace llvm; 24f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner 2549a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on. 2649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnernamespace llvm { extern raw_ostream *CreateInfoOutputFile(); } 27d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 2871336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy 2971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// of constructor/destructor ordering being unspecified by C++. Basically the 30ac0b6ae358944ae8b2b5a11dc08f52c3ed89f2daChris Lattner// problem is that a Statistic object gets destroyed, which ends up calling 3171336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// 'GetLibSupportInfoOutputFile()' (below), which calls this function. 3271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// LibSupportInfoOutputFilename used to be a global variable, but sometimes it 33f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// would get destroyed before the Statistic, causing havoc to ensue. We "fix" 34f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// this by creating the string the first time it is needed and never destroying 35f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// it. 3690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::string> LibSupportInfoOutputFilename; 3771336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattnerstatic std::string &getLibSupportInfoOutputFilename() { 38f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer return *LibSupportInfoOutputFilename; 3971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner} 406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 4146d9a6494496d215e850f337b5a723c484212f80Owen Andersonstatic ManagedStatic<sys::SmartMutex<true> > TimerLock; 4246d9a6494496d215e850f337b5a723c484212f80Owen Anderson 433f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattnernamespace { 443c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman static cl::opt<bool> 453f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner TrackSpace("track-memory", cl::desc("Enable -time-passes memory " 463f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner "tracking (this may be slow)"), 473f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner cl::Hidden); 48f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner 493c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman static cl::opt<std::string, true> 5096a54db5e763c19f556a1b54ad2956cc91b81cb8Chris Lattner InfoOutputFilename("info-output-file", cl::value_desc("filename"), 51f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner cl::desc("File to append -stats and -timer output to"), 5271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); 533f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner} 543f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner 5549a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on. 5649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnerraw_ostream *llvm::CreateInfoOutputFile() { 57cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner const std::string &OutputFilename = getLibSupportInfoOutputFilename(); 58cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner if (OutputFilename.empty()) 5949a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(2, false); // stderr. 60cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner if (OutputFilename == "-") 6149a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(1, false); // stdout. 62f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 6386026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // Append mode is used because the info output file is opened and closed 6486026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // each time -stats or -time-passes wants to print output to it. To 6586026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // compensate for this, the test-suite Makefiles have code to delete the 6686026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman // info output file before running commands which write to it. 6737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::error_code EC; 6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines raw_ostream *Result = new raw_fd_ostream(OutputFilename, EC, 6937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sys::fs::F_Append | sys::fs::F_Text); 7037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!EC) 71f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner return Result; 72f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 73f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner errs() << "Error opening info-output-file '" 74cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner << OutputFilename << " for appending!\n"; 75f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner delete Result; 7649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner return new raw_fd_ostream(2, false); // stderr. 77f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner} 78f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 79f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner 80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic TimerGroup *DefaultTimerGroup = nullptr; 816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() { 829bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner TimerGroup *tmp = DefaultTimerGroup; 833b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson sys::MemoryFence(); 849bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner if (tmp) return tmp; 859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 86c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines sys::SmartScopedLock<true> Lock(*TimerLock); 879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner tmp = DefaultTimerGroup; 883b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson if (!tmp) { 899bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); 909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::MemoryFence(); 919bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner DefaultTimerGroup = tmp; 923b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson } 93c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov 943b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson return tmp; 956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 966c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 979bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===// 989bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation 999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===// 1009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 101cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N) { 102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(!TG && "Timer already initialized"); 103cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Name.assign(N.begin(), N.end()); 104a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Started = false; 105a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TG = getDefaultTimerGroup(); 106b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->addTimer(*this); 1076c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 109cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N, TimerGroup &tg) { 110dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(!TG && "Timer already initialized"); 111cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Name.assign(N.begin(), N.end()); 112a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Started = false; 113a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TG = &tg; 114b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->addTimer(*this); 1156c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1166c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() { 118ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TG) return; // Never initialized, or already cleared. 119b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TG->removeTimer(*this); 1206c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 122e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() { 123ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TrackSpace) return 0; 124ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner return sys::Process::GetMallocUsage(); 125aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer} 126aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer 127a782e75d487006cafffdc256b3c623307fee4dcfChris LattnerTimeRecord TimeRecord::getCurrentTime(bool Start) { 128df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer TimeRecord Result; 129ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::TimeValue now(0,0), user(0,0), sys(0,0); 130ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 1317d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer if (Start) { 132ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Result.MemUsed = getMemUsage(); 1339bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::Process::GetTimeUsage(now, user, sys); 1347d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer } else { 1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner sys::Process::GetTimeUsage(now, user, sys); 136ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Result.MemUsed = getMemUsage(); 1377d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer } 1388f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 139a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; 1409bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; 141a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; 1426c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner return Result; 1436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 14590aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers; 1468f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 1476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() { 1486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner Started = true; 149153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman ActiveTimers->push_back(this); 150a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Time -= TimeRecord::getCurrentTime(true); 1516c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() { 154a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Time += TimeRecord::getCurrentTime(false); 1558f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 15690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner if (ActiveTimers->back() == this) { 15790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner ActiveTimers->pop_back(); 1588f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner } else { 1598f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner std::vector<Timer*>::iterator I = 16090aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner std::find(ActiveTimers->begin(), ActiveTimers->end(), this); 16190aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner assert(I != ActiveTimers->end() && "stop but no startTimer?"); 16290aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner ActiveTimers->erase(I); 1638f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner } 1646c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner} 1656c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 1669bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) { 1670613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner if (Total < 1e-7) // Avoid dividing by zero. 1689bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner OS << " ----- "; 169962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer else 170962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total); 1719bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner} 1729bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 173a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const { 174a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getUserTime()) 175a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getUserTime(), Total.getUserTime(), OS); 176a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getSystemTime()) 177a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getSystemTime(), Total.getSystemTime(), OS); 1789bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner if (Total.getProcessTime()) 1799bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner printVal(getProcessTime(), Total.getProcessTime(), OS); 180a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner printVal(getWallTime(), Total.getWallTime(), OS); 1819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 1829bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner OS << " "; 1839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 184a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getMemUsed()) 18541a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer OS << format("%9" PRId64 " ", (int64_t)getMemUsed()); 1869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner} 1879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 1889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 189d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===// 190d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner// NamedRegionTimer Implementation 191d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===// 192d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 193b35798347ea87b8b6d36155b211016a7769f01abDan Gohmannamespace { 194b35798347ea87b8b6d36155b211016a7769f01abDan Gohman 195a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<Timer> Name2TimerMap; 196ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 197ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerclass Name2PairMap { 198ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map; 199ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerpublic: 200ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner ~Name2PairMap() { 201ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator 202ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner I = Map.begin(), E = Map.end(); I != E; ++I) 203ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner delete I->second.first; 204ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 205ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 206cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner Timer &get(StringRef Name, StringRef GroupName) { 207ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 208ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 209ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName]; 210ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 211ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!GroupEntry.first) 212ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner GroupEntry.first = new TimerGroup(GroupName); 213ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 214ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner Timer &T = GroupEntry.second[Name]; 215ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!T.isInitialized()) 216ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T.init(Name, *GroupEntry.first); 217ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner return T; 218ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 219ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner}; 2205e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman 221b35798347ea87b8b6d36155b211016a7769f01abDan Gohman} 222b35798347ea87b8b6d36155b211016a7769f01abDan Gohman 223a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2TimerMap> NamedTimers; 224a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2PairMap> NamedGroupedTimers; 225d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 226cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnerstatic Timer &getNamedRegionTimer(StringRef Name) { 227a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::SmartScopedLock<true> L(*TimerLock); 228a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner 229a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Timer &T = (*NamedTimers)[Name]; 230a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (!T.isInitialized()) 231a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner T.init(Name); 232a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner return T; 233d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner} 234d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 23503c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, 23603c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman bool Enabled) 237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {} 238d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner 23903c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName, 24003c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman bool Enabled) 241dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){} 2428f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner 2436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===// 2446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// TimerGroup Implementation 2456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===// 2466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner 24783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroupList - This is the global list of TimerGroups, maintained by the 24883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroup ctor/dtor and is protected by the TimerLock lock. 249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic TimerGroup *TimerGroupList = nullptr; 25083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 251cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris LattnerTimerGroup::TimerGroup(StringRef name) 252dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : Name(name.begin(), name.end()), FirstTimer(nullptr) { 25383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 25483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner // Add the group to TimerGroupList. 25583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 25683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner if (TimerGroupList) 25783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TimerGroupList->Prev = &Next; 25883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Next = TimerGroupList; 25983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Prev = &TimerGroupList; 26083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TimerGroupList = this; 26183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner} 26283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 2639f9f6d19dd67926446fb89a7b2dc0bda6353645bChris LattnerTimerGroup::~TimerGroup() { 2649f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner // If the timer group is destroyed before the timers it owns, accumulate and 2659f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner // print the timing data. 266dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines while (FirstTimer) 2679f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner removeTimer(*FirstTimer); 26883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 26983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner // Remove the group from the TimerGroupList. 27083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 27183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner *Prev = Next; 27283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner if (Next) 27383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner Next->Prev = Prev; 2749f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner} 2759f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 2769f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 277b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::removeTimer(Timer &T) { 278a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson sys::SmartScopedLock<true> L(*TimerLock); 2799bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 280b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // If the timer was started, move its data to TimersToPrint. 2819f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner if (T.Started) 282b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner TimersToPrint.push_back(std::make_pair(T.Time, T.Name)); 2839f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner 284dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines T.TG = nullptr; 285b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 286b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Unlink the timer from our list. 287b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner *T.Prev = T.Next; 288b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (T.Next) 289b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Next->Prev = T.Prev; 290b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 291b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Print the report when all timers in this group are destroyed if some of 292b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // them were started. 293dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (FirstTimer || TimersToPrint.empty()) 294b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner return; 295b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 29649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner raw_ostream *OutStream = CreateInfoOutputFile(); 297b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner PrintQueuedTimers(*OutStream); 29849a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner delete OutStream; // Close the file. 299b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner} 300b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 301b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::addTimer(Timer &T) { 302b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 303b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 304b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Add the timer to our list. 305b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (FirstTimer) 306b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner FirstTimer->Prev = &T.Next; 307b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Next = FirstTimer; 308b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner T.Prev = &FirstTimer; 309b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner FirstTimer = &T; 310b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner} 3119bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner 312b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::PrintQueuedTimers(raw_ostream &OS) { 313b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Sort the timers in descending order by amount of time taken. 314fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer std::sort(TimersToPrint.begin(), TimersToPrint.end()); 315fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer 316a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner TimeRecord Total; 317a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) 318a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner Total += TimersToPrint[i].first; 319b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 320a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Print out timing header. 321b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "===" << std::string(73, '-') << "===\n"; 322b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner // Figure out how many spaces to indent TimerGroup name. 323b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner unsigned Padding = (80-Name.length())/2; 324b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner if (Padding > 80) Padding = 0; // Don't allow "negative" numbers 325b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS.indent(Padding) << Name << '\n'; 326b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "===" << std::string(73, '-') << "===\n"; 327b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 328a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // If this is not an collection of ungrouped times, print the total time. 329a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Ungrouped timers don't really make sense to add up. We still print the 330a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // TOTAL line to make the percentages make sense. 331962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer if (this != DefaultTimerGroup) 332962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n", 333962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer Total.getProcessTime(), Total.getWallTime()); 334b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << '\n'; 335b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 336a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getUserTime()) 337b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---User Time---"; 338a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getSystemTime()) 339b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --System Time--"; 340a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getProcessTime()) 341b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --User+System--"; 342b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---Wall Time---"; 343a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner if (Total.getMemUsed()) 344b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " ---Mem---"; 345b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << " --- Name ---\n"; 346b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 347a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner // Loop through all of the timing data, printing it out. 348a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) { 349a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1]; 350b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner Entry.first.print(Total, OS); 351b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << Entry.second << '\n'; 352a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner } 353b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 354b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner Total.print(Total, OS); 355b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS << "Total\n\n"; 356b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner OS.flush(); 357b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner 3589bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner TimersToPrint.clear(); 35946d9a6494496d215e850f337b5a723c484212f80Owen Anderson} 36046d9a6494496d215e850f337b5a723c484212f80Owen Anderson 361ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner/// print - Print any started timers in this group and zero them. 362ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnervoid TimerGroup::print(raw_ostream &OS) { 363ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 364ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 365ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // See if any of our timers were started, if so add them to TimersToPrint and 366ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // reset them. 367ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner for (Timer *T = FirstTimer; T; T = T->Next) { 368ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!T->Started) continue; 369ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner TimersToPrint.push_back(std::make_pair(T->Time, T->Name)); 370ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 371ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // Clear out the time. 372ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T->Started = 0; 373ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner T->Time = TimeRecord(); 374ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner } 375ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner 376ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner // If any timers were started, print the group. 377ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner if (!TimersToPrint.empty()) 378ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner PrintQueuedTimers(OS); 379ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner} 38083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 38183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// printAll - This static method prints all timers and clears them all out. 38283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnervoid TimerGroup::printAll(raw_ostream &OS) { 38383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner sys::SmartScopedLock<true> L(*TimerLock); 38483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner 38583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) 38683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner TG->print(OS); 38783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner} 388