xref: /aosp_15_r20/external/llvm/lib/Support/Timer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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