1*9880d681SAndroid Build Coastguard Worker //===-- Timer.cpp - Interval Timing Support -------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Interval Timing implementation.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Timer.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringMap.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Mutex.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Process.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker
26*9880d681SAndroid Build Coastguard Worker // getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
27*9880d681SAndroid Build Coastguard Worker // of constructor/destructor ordering being unspecified by C++. Basically the
28*9880d681SAndroid Build Coastguard Worker // problem is that a Statistic object gets destroyed, which ends up calling
29*9880d681SAndroid Build Coastguard Worker // 'GetLibSupportInfoOutputFile()' (below), which calls this function.
30*9880d681SAndroid Build Coastguard Worker // LibSupportInfoOutputFilename used to be a global variable, but sometimes it
31*9880d681SAndroid Build Coastguard Worker // would get destroyed before the Statistic, causing havoc to ensue. We "fix"
32*9880d681SAndroid Build Coastguard Worker // this by creating the string the first time it is needed and never destroying
33*9880d681SAndroid Build Coastguard Worker // it.
34*9880d681SAndroid Build Coastguard Worker static ManagedStatic<std::string> LibSupportInfoOutputFilename;
getLibSupportInfoOutputFilename()35*9880d681SAndroid Build Coastguard Worker static std::string &getLibSupportInfoOutputFilename() {
36*9880d681SAndroid Build Coastguard Worker return *LibSupportInfoOutputFilename;
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker static ManagedStatic<sys::SmartMutex<true> > TimerLock;
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker namespace {
42*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
43*9880d681SAndroid Build Coastguard Worker TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
44*9880d681SAndroid Build Coastguard Worker "tracking (this may be slow)"),
45*9880d681SAndroid Build Coastguard Worker cl::Hidden);
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string, true>
48*9880d681SAndroid Build Coastguard Worker InfoOutputFilename("info-output-file", cl::value_desc("filename"),
49*9880d681SAndroid Build Coastguard Worker cl::desc("File to append -stats and -timer output to"),
50*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker // Return a file stream to print our output on.
CreateInfoOutputFile()54*9880d681SAndroid Build Coastguard Worker std::unique_ptr<raw_fd_ostream> llvm::CreateInfoOutputFile() {
55*9880d681SAndroid Build Coastguard Worker const std::string &OutputFilename = getLibSupportInfoOutputFilename();
56*9880d681SAndroid Build Coastguard Worker if (OutputFilename.empty())
57*9880d681SAndroid Build Coastguard Worker return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
58*9880d681SAndroid Build Coastguard Worker if (OutputFilename == "-")
59*9880d681SAndroid Build Coastguard Worker return llvm::make_unique<raw_fd_ostream>(1, false); // stdout.
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Append mode is used because the info output file is opened and closed
62*9880d681SAndroid Build Coastguard Worker // each time -stats or -time-passes wants to print output to it. To
63*9880d681SAndroid Build Coastguard Worker // compensate for this, the test-suite Makefiles have code to delete the
64*9880d681SAndroid Build Coastguard Worker // info output file before running commands which write to it.
65*9880d681SAndroid Build Coastguard Worker std::error_code EC;
66*9880d681SAndroid Build Coastguard Worker auto Result = llvm::make_unique<raw_fd_ostream>(
67*9880d681SAndroid Build Coastguard Worker OutputFilename, EC, sys::fs::F_Append | sys::fs::F_Text);
68*9880d681SAndroid Build Coastguard Worker if (!EC)
69*9880d681SAndroid Build Coastguard Worker return Result;
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker errs() << "Error opening info-output-file '"
72*9880d681SAndroid Build Coastguard Worker << OutputFilename << " for appending!\n";
73*9880d681SAndroid Build Coastguard Worker return llvm::make_unique<raw_fd_ostream>(2, false); // stderr.
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker static TimerGroup *DefaultTimerGroup = nullptr;
getDefaultTimerGroup()78*9880d681SAndroid Build Coastguard Worker static TimerGroup *getDefaultTimerGroup() {
79*9880d681SAndroid Build Coastguard Worker TimerGroup *tmp = DefaultTimerGroup;
80*9880d681SAndroid Build Coastguard Worker sys::MemoryFence();
81*9880d681SAndroid Build Coastguard Worker if (tmp) return tmp;
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> Lock(*TimerLock);
84*9880d681SAndroid Build Coastguard Worker tmp = DefaultTimerGroup;
85*9880d681SAndroid Build Coastguard Worker if (!tmp) {
86*9880d681SAndroid Build Coastguard Worker tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
87*9880d681SAndroid Build Coastguard Worker sys::MemoryFence();
88*9880d681SAndroid Build Coastguard Worker DefaultTimerGroup = tmp;
89*9880d681SAndroid Build Coastguard Worker }
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker return tmp;
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker
94*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
95*9880d681SAndroid Build Coastguard Worker // Timer Implementation
96*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
97*9880d681SAndroid Build Coastguard Worker
init(StringRef N)98*9880d681SAndroid Build Coastguard Worker void Timer::init(StringRef N) {
99*9880d681SAndroid Build Coastguard Worker init(N, *getDefaultTimerGroup());
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
init(StringRef N,TimerGroup & tg)102*9880d681SAndroid Build Coastguard Worker void Timer::init(StringRef N, TimerGroup &tg) {
103*9880d681SAndroid Build Coastguard Worker assert(!TG && "Timer already initialized");
104*9880d681SAndroid Build Coastguard Worker Name.assign(N.begin(), N.end());
105*9880d681SAndroid Build Coastguard Worker Running = Triggered = false;
106*9880d681SAndroid Build Coastguard Worker TG = &tg;
107*9880d681SAndroid Build Coastguard Worker TG->addTimer(*this);
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
~Timer()110*9880d681SAndroid Build Coastguard Worker Timer::~Timer() {
111*9880d681SAndroid Build Coastguard Worker if (!TG) return; // Never initialized, or already cleared.
112*9880d681SAndroid Build Coastguard Worker TG->removeTimer(*this);
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
getMemUsage()115*9880d681SAndroid Build Coastguard Worker static inline size_t getMemUsage() {
116*9880d681SAndroid Build Coastguard Worker if (!TrackSpace) return 0;
117*9880d681SAndroid Build Coastguard Worker return sys::Process::GetMallocUsage();
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker
getCurrentTime(bool Start)120*9880d681SAndroid Build Coastguard Worker TimeRecord TimeRecord::getCurrentTime(bool Start) {
121*9880d681SAndroid Build Coastguard Worker TimeRecord Result;
122*9880d681SAndroid Build Coastguard Worker sys::TimeValue now(0,0), user(0,0), sys(0,0);
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker if (Start) {
125*9880d681SAndroid Build Coastguard Worker Result.MemUsed = getMemUsage();
126*9880d681SAndroid Build Coastguard Worker sys::Process::GetTimeUsage(now, user, sys);
127*9880d681SAndroid Build Coastguard Worker } else {
128*9880d681SAndroid Build Coastguard Worker sys::Process::GetTimeUsage(now, user, sys);
129*9880d681SAndroid Build Coastguard Worker Result.MemUsed = getMemUsage();
130*9880d681SAndroid Build Coastguard Worker }
131*9880d681SAndroid Build Coastguard Worker
132*9880d681SAndroid Build Coastguard Worker Result.WallTime = now.seconds() + now.microseconds() / 1000000.0;
133*9880d681SAndroid Build Coastguard Worker Result.UserTime = user.seconds() + user.microseconds() / 1000000.0;
134*9880d681SAndroid Build Coastguard Worker Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0;
135*9880d681SAndroid Build Coastguard Worker return Result;
136*9880d681SAndroid Build Coastguard Worker }
137*9880d681SAndroid Build Coastguard Worker
startTimer()138*9880d681SAndroid Build Coastguard Worker void Timer::startTimer() {
139*9880d681SAndroid Build Coastguard Worker assert(!Running && "Cannot start a running timer");
140*9880d681SAndroid Build Coastguard Worker Running = Triggered = true;
141*9880d681SAndroid Build Coastguard Worker StartTime = TimeRecord::getCurrentTime(true);
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker
stopTimer()144*9880d681SAndroid Build Coastguard Worker void Timer::stopTimer() {
145*9880d681SAndroid Build Coastguard Worker assert(Running && "Cannot stop a paused timer");
146*9880d681SAndroid Build Coastguard Worker Running = false;
147*9880d681SAndroid Build Coastguard Worker Time += TimeRecord::getCurrentTime(false);
148*9880d681SAndroid Build Coastguard Worker Time -= StartTime;
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker
clear()151*9880d681SAndroid Build Coastguard Worker void Timer::clear() {
152*9880d681SAndroid Build Coastguard Worker Running = Triggered = false;
153*9880d681SAndroid Build Coastguard Worker Time = StartTime = TimeRecord();
154*9880d681SAndroid Build Coastguard Worker }
155*9880d681SAndroid Build Coastguard Worker
printVal(double Val,double Total,raw_ostream & OS)156*9880d681SAndroid Build Coastguard Worker static void printVal(double Val, double Total, raw_ostream &OS) {
157*9880d681SAndroid Build Coastguard Worker if (Total < 1e-7) // Avoid dividing by zero.
158*9880d681SAndroid Build Coastguard Worker OS << " ----- ";
159*9880d681SAndroid Build Coastguard Worker else
160*9880d681SAndroid Build Coastguard Worker OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total);
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker
print(const TimeRecord & Total,raw_ostream & OS) const163*9880d681SAndroid Build Coastguard Worker void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
164*9880d681SAndroid Build Coastguard Worker if (Total.getUserTime())
165*9880d681SAndroid Build Coastguard Worker printVal(getUserTime(), Total.getUserTime(), OS);
166*9880d681SAndroid Build Coastguard Worker if (Total.getSystemTime())
167*9880d681SAndroid Build Coastguard Worker printVal(getSystemTime(), Total.getSystemTime(), OS);
168*9880d681SAndroid Build Coastguard Worker if (Total.getProcessTime())
169*9880d681SAndroid Build Coastguard Worker printVal(getProcessTime(), Total.getProcessTime(), OS);
170*9880d681SAndroid Build Coastguard Worker printVal(getWallTime(), Total.getWallTime(), OS);
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker OS << " ";
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker if (Total.getMemUsed())
175*9880d681SAndroid Build Coastguard Worker OS << format("%9" PRId64 " ", (int64_t)getMemUsed());
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
180*9880d681SAndroid Build Coastguard Worker // NamedRegionTimer Implementation
181*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker namespace {
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker typedef StringMap<Timer> Name2TimerMap;
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker class Name2PairMap {
188*9880d681SAndroid Build Coastguard Worker StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map;
189*9880d681SAndroid Build Coastguard Worker public:
~Name2PairMap()190*9880d681SAndroid Build Coastguard Worker ~Name2PairMap() {
191*9880d681SAndroid Build Coastguard Worker for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator
192*9880d681SAndroid Build Coastguard Worker I = Map.begin(), E = Map.end(); I != E; ++I)
193*9880d681SAndroid Build Coastguard Worker delete I->second.first;
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
get(StringRef Name,StringRef GroupName)196*9880d681SAndroid Build Coastguard Worker Timer &get(StringRef Name, StringRef GroupName) {
197*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Worker std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker if (!GroupEntry.first)
202*9880d681SAndroid Build Coastguard Worker GroupEntry.first = new TimerGroup(GroupName);
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker Timer &T = GroupEntry.second[Name];
205*9880d681SAndroid Build Coastguard Worker if (!T.isInitialized())
206*9880d681SAndroid Build Coastguard Worker T.init(Name, *GroupEntry.first);
207*9880d681SAndroid Build Coastguard Worker return T;
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker };
210*9880d681SAndroid Build Coastguard Worker
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker static ManagedStatic<Name2TimerMap> NamedTimers;
214*9880d681SAndroid Build Coastguard Worker static ManagedStatic<Name2PairMap> NamedGroupedTimers;
215*9880d681SAndroid Build Coastguard Worker
getNamedRegionTimer(StringRef Name)216*9880d681SAndroid Build Coastguard Worker static Timer &getNamedRegionTimer(StringRef Name) {
217*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
218*9880d681SAndroid Build Coastguard Worker
219*9880d681SAndroid Build Coastguard Worker Timer &T = (*NamedTimers)[Name];
220*9880d681SAndroid Build Coastguard Worker if (!T.isInitialized())
221*9880d681SAndroid Build Coastguard Worker T.init(Name);
222*9880d681SAndroid Build Coastguard Worker return T;
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
NamedRegionTimer(StringRef Name,bool Enabled)225*9880d681SAndroid Build Coastguard Worker NamedRegionTimer::NamedRegionTimer(StringRef Name,
226*9880d681SAndroid Build Coastguard Worker bool Enabled)
227*9880d681SAndroid Build Coastguard Worker : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {}
228*9880d681SAndroid Build Coastguard Worker
NamedRegionTimer(StringRef Name,StringRef GroupName,bool Enabled)229*9880d681SAndroid Build Coastguard Worker NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName,
230*9880d681SAndroid Build Coastguard Worker bool Enabled)
231*9880d681SAndroid Build Coastguard Worker : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){}
232*9880d681SAndroid Build Coastguard Worker
233*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
234*9880d681SAndroid Build Coastguard Worker // TimerGroup Implementation
235*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
236*9880d681SAndroid Build Coastguard Worker
237*9880d681SAndroid Build Coastguard Worker /// TimerGroupList - This is the global list of TimerGroups, maintained by the
238*9880d681SAndroid Build Coastguard Worker /// TimerGroup ctor/dtor and is protected by the TimerLock lock.
239*9880d681SAndroid Build Coastguard Worker static TimerGroup *TimerGroupList = nullptr;
240*9880d681SAndroid Build Coastguard Worker
TimerGroup(StringRef name)241*9880d681SAndroid Build Coastguard Worker TimerGroup::TimerGroup(StringRef name)
242*9880d681SAndroid Build Coastguard Worker : Name(name.begin(), name.end()), FirstTimer(nullptr) {
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker // Add the group to TimerGroupList.
245*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
246*9880d681SAndroid Build Coastguard Worker if (TimerGroupList)
247*9880d681SAndroid Build Coastguard Worker TimerGroupList->Prev = &Next;
248*9880d681SAndroid Build Coastguard Worker Next = TimerGroupList;
249*9880d681SAndroid Build Coastguard Worker Prev = &TimerGroupList;
250*9880d681SAndroid Build Coastguard Worker TimerGroupList = this;
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker
~TimerGroup()253*9880d681SAndroid Build Coastguard Worker TimerGroup::~TimerGroup() {
254*9880d681SAndroid Build Coastguard Worker // If the timer group is destroyed before the timers it owns, accumulate and
255*9880d681SAndroid Build Coastguard Worker // print the timing data.
256*9880d681SAndroid Build Coastguard Worker while (FirstTimer)
257*9880d681SAndroid Build Coastguard Worker removeTimer(*FirstTimer);
258*9880d681SAndroid Build Coastguard Worker
259*9880d681SAndroid Build Coastguard Worker // Remove the group from the TimerGroupList.
260*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
261*9880d681SAndroid Build Coastguard Worker *Prev = Next;
262*9880d681SAndroid Build Coastguard Worker if (Next)
263*9880d681SAndroid Build Coastguard Worker Next->Prev = Prev;
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
266*9880d681SAndroid Build Coastguard Worker
removeTimer(Timer & T)267*9880d681SAndroid Build Coastguard Worker void TimerGroup::removeTimer(Timer &T) {
268*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
269*9880d681SAndroid Build Coastguard Worker
270*9880d681SAndroid Build Coastguard Worker // If the timer was started, move its data to TimersToPrint.
271*9880d681SAndroid Build Coastguard Worker if (T.hasTriggered())
272*9880d681SAndroid Build Coastguard Worker TimersToPrint.emplace_back(T.Time, T.Name);
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker T.TG = nullptr;
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker // Unlink the timer from our list.
277*9880d681SAndroid Build Coastguard Worker *T.Prev = T.Next;
278*9880d681SAndroid Build Coastguard Worker if (T.Next)
279*9880d681SAndroid Build Coastguard Worker T.Next->Prev = T.Prev;
280*9880d681SAndroid Build Coastguard Worker
281*9880d681SAndroid Build Coastguard Worker // Print the report when all timers in this group are destroyed if some of
282*9880d681SAndroid Build Coastguard Worker // them were started.
283*9880d681SAndroid Build Coastguard Worker if (FirstTimer || TimersToPrint.empty())
284*9880d681SAndroid Build Coastguard Worker return;
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
287*9880d681SAndroid Build Coastguard Worker PrintQueuedTimers(*OutStream);
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker
addTimer(Timer & T)290*9880d681SAndroid Build Coastguard Worker void TimerGroup::addTimer(Timer &T) {
291*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker // Add the timer to our list.
294*9880d681SAndroid Build Coastguard Worker if (FirstTimer)
295*9880d681SAndroid Build Coastguard Worker FirstTimer->Prev = &T.Next;
296*9880d681SAndroid Build Coastguard Worker T.Next = FirstTimer;
297*9880d681SAndroid Build Coastguard Worker T.Prev = &FirstTimer;
298*9880d681SAndroid Build Coastguard Worker FirstTimer = &T;
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker
PrintQueuedTimers(raw_ostream & OS)301*9880d681SAndroid Build Coastguard Worker void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
302*9880d681SAndroid Build Coastguard Worker // Sort the timers in descending order by amount of time taken.
303*9880d681SAndroid Build Coastguard Worker std::sort(TimersToPrint.begin(), TimersToPrint.end());
304*9880d681SAndroid Build Coastguard Worker
305*9880d681SAndroid Build Coastguard Worker TimeRecord Total;
306*9880d681SAndroid Build Coastguard Worker for (auto &RecordNamePair : TimersToPrint)
307*9880d681SAndroid Build Coastguard Worker Total += RecordNamePair.first;
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker // Print out timing header.
310*9880d681SAndroid Build Coastguard Worker OS << "===" << std::string(73, '-') << "===\n";
311*9880d681SAndroid Build Coastguard Worker // Figure out how many spaces to indent TimerGroup name.
312*9880d681SAndroid Build Coastguard Worker unsigned Padding = (80-Name.length())/2;
313*9880d681SAndroid Build Coastguard Worker if (Padding > 80) Padding = 0; // Don't allow "negative" numbers
314*9880d681SAndroid Build Coastguard Worker OS.indent(Padding) << Name << '\n';
315*9880d681SAndroid Build Coastguard Worker OS << "===" << std::string(73, '-') << "===\n";
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker // If this is not an collection of ungrouped times, print the total time.
318*9880d681SAndroid Build Coastguard Worker // Ungrouped timers don't really make sense to add up. We still print the
319*9880d681SAndroid Build Coastguard Worker // TOTAL line to make the percentages make sense.
320*9880d681SAndroid Build Coastguard Worker if (this != DefaultTimerGroup)
321*9880d681SAndroid Build Coastguard Worker OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
322*9880d681SAndroid Build Coastguard Worker Total.getProcessTime(), Total.getWallTime());
323*9880d681SAndroid Build Coastguard Worker OS << '\n';
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker if (Total.getUserTime())
326*9880d681SAndroid Build Coastguard Worker OS << " ---User Time---";
327*9880d681SAndroid Build Coastguard Worker if (Total.getSystemTime())
328*9880d681SAndroid Build Coastguard Worker OS << " --System Time--";
329*9880d681SAndroid Build Coastguard Worker if (Total.getProcessTime())
330*9880d681SAndroid Build Coastguard Worker OS << " --User+System--";
331*9880d681SAndroid Build Coastguard Worker OS << " ---Wall Time---";
332*9880d681SAndroid Build Coastguard Worker if (Total.getMemUsed())
333*9880d681SAndroid Build Coastguard Worker OS << " ---Mem---";
334*9880d681SAndroid Build Coastguard Worker OS << " --- Name ---\n";
335*9880d681SAndroid Build Coastguard Worker
336*9880d681SAndroid Build Coastguard Worker // Loop through all of the timing data, printing it out.
337*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
338*9880d681SAndroid Build Coastguard Worker const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
339*9880d681SAndroid Build Coastguard Worker Entry.first.print(Total, OS);
340*9880d681SAndroid Build Coastguard Worker OS << Entry.second << '\n';
341*9880d681SAndroid Build Coastguard Worker }
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker Total.print(Total, OS);
344*9880d681SAndroid Build Coastguard Worker OS << "Total\n\n";
345*9880d681SAndroid Build Coastguard Worker OS.flush();
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker TimersToPrint.clear();
348*9880d681SAndroid Build Coastguard Worker }
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker /// print - Print any started timers in this group and zero them.
print(raw_ostream & OS)351*9880d681SAndroid Build Coastguard Worker void TimerGroup::print(raw_ostream &OS) {
352*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
353*9880d681SAndroid Build Coastguard Worker
354*9880d681SAndroid Build Coastguard Worker // See if any of our timers were started, if so add them to TimersToPrint and
355*9880d681SAndroid Build Coastguard Worker // reset them.
356*9880d681SAndroid Build Coastguard Worker for (Timer *T = FirstTimer; T; T = T->Next) {
357*9880d681SAndroid Build Coastguard Worker if (!T->hasTriggered()) continue;
358*9880d681SAndroid Build Coastguard Worker TimersToPrint.emplace_back(T->Time, T->Name);
359*9880d681SAndroid Build Coastguard Worker
360*9880d681SAndroid Build Coastguard Worker // Clear out the time.
361*9880d681SAndroid Build Coastguard Worker T->clear();
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker // If any timers were started, print the group.
365*9880d681SAndroid Build Coastguard Worker if (!TimersToPrint.empty())
366*9880d681SAndroid Build Coastguard Worker PrintQueuedTimers(OS);
367*9880d681SAndroid Build Coastguard Worker }
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker /// printAll - This static method prints all timers and clears them all out.
printAll(raw_ostream & OS)370*9880d681SAndroid Build Coastguard Worker void TimerGroup::printAll(raw_ostream &OS) {
371*9880d681SAndroid Build Coastguard Worker sys::SmartScopedLock<true> L(*TimerLock);
372*9880d681SAndroid Build Coastguard Worker
373*9880d681SAndroid Build Coastguard Worker for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
374*9880d681SAndroid Build Coastguard Worker TG->print(OS);
375*9880d681SAndroid Build Coastguard Worker }
376