LLVM: lib/Support/Timer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
14
16
19#include "llvm/Config/config.h"
28#include
29#include
30
31#if HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34
35#ifdef HAVE_PROC_PID_RUSAGE
36#include <libproc.h>
37#endif
38
39using namespace llvm;
40
41
42
43
44
45
46
47
48namespace {
49class Name2PairMap;
50}
51
55[[maybe_unused]]
61
62
63
64
65
69 return std::make_unique<raw_fd_ostream>(2, false);
71 return std::make_unique<raw_fd_ostream>(1, false);
72
73
74
75
76
77 std::error_code EC;
78 auto Result = std::make_unique<raw_fd_ostream>(
80 if (!EC)
81 return Result;
82
83 errs() << "Error opening info-output-file '"
85 return std::make_unique<raw_fd_ostream>(2, false);
86}
87
88
89
90
91
95
98 assert(!TG && "Timer already initialized");
99 Name.assign(TimerName.begin(), TimerName.end());
100 Description.assign(TimerDescription.begin(), TimerDescription.end());
101 Running = Triggered = false;
102 TG = &tg;
103 TG->addTimer(*this);
104}
105
107 if (!TG) return;
108 TG->removeTimer(*this);
109}
110
116
118#if defined(HAVE_UNISTD_H) && defined(HAVE_PROC_PID_RUSAGE) && \
119 defined(RUSAGE_INFO_V4)
120 struct rusage_info_v4 ru;
121 if (proc_pid_rusage(getpid(), RUSAGE_INFO_V4, (rusage_info_t *)&ru) == 0) {
122 return ru.ri_instructions;
123 }
124#endif
125 return 0;
126}
127
129 using Seconds = std::chrono::duration<double, std::ratio<1>>;
132 std::chrono::nanoseconds user, sys;
133
134 if (Start) {
138 } else {
142 }
143
144 Result.WallTime = Seconds(now.time_since_epoch()).count();
145 Result.UserTime = Seconds(user).count();
146 Result.SystemTime = Seconds(sys).count();
147 return Result;
148}
149
151 assert(!Running && "Cannot start a running timer");
152 Running = Triggered = true;
153#if LLVM_SUPPORT_XCODE_SIGNPOSTS
155#endif
157}
158
160 assert(Running && "Cannot stop a paused timer");
161 Running = false;
163 Time -= StartTime;
164#if LLVM_SUPPORT_XCODE_SIGNPOSTS
166#endif
167}
168
170 Running = Triggered = false;
172}
173
178
180 if (Total < 1e-7)
181 OS << " ----- ";
182 else
183 OS << format(" %7.4f (%5.1f%%)", Val, Val*100/Total);
184}
185
187 if (Total.getUserTime())
189 if (Total.getSystemTime())
191 if (Total.getProcessTime())
194
195 OS << " ";
196
197 if (Total.getMemUsed())
199 if (Total.getInstructionsExecuted())
201}
202
203
204
205
206
207
208namespace {
209
211
212class Name2PairMap {
214public:
215 ~Name2PairMap() {
217 I = Map.begin(), E = Map.end(); I != E; ++I)
218 delete I->second.first;
219 }
220
224
225 std::pair<TimerGroup *, Name2TimerMap> &GroupEntry =
226 getGroupEntry(GroupName, GroupDescription);
227 Timer &T = GroupEntry.second[Name];
228 if (.isInitialized())
229 T.init(Name, Description, *GroupEntry.first);
230 return T;
231 }
232
233 TimerGroup &getTimerGroup(StringRef GroupName, StringRef GroupDescription) {
235 return *getGroupEntry(GroupName, GroupDescription).first;
236 }
237
238private:
239 std::pair<TimerGroup *, Name2TimerMap> &
240 getGroupEntry(StringRef GroupName, StringRef GroupDescription) {
241 std::pair<TimerGroup *, Name2TimerMap> &GroupEntry = Map[GroupName];
242 if (!GroupEntry.first)
243 GroupEntry.first =
244 new TimerGroup(GroupName, GroupDescription, true);
245
246 return GroupEntry;
247 }
248};
249
250}
251
256 ? nullptr
258 GroupDescription)) {}
259
264
265
266
267
268
269
270
272
275 : Name(Name.begin(), Name.end()),
276 Description(Description.begin(), Description.end()),
278
285}
286
288 : TimerGroup(Name, Description, timerLock(), PrintOnExit) {}
289
292 : TimerGroup(Name, Description, PrintOnExit) {
293 TimersToPrint.reserve(Records.size());
294 for (const auto &P : Records)
295 TimersToPrint.emplace_back(P.getValue(), std::string(P.getKey()),
296 std::string(P.getKey()));
297 assert(TimersToPrint.size() == Records.size() && "Size mismatch");
298}
299
301
302
303 while (FirstTimer)
304 removeTimer(*FirstTimer);
305
306 if (!TimersToPrint.empty() && PrintOnExit) {
308 PrintQueuedTimers(*OutStream);
309 }
310
311 auto unlink = [&]() {
312 *Prev = Next;
313 if (Next)
314 Next->Prev = Prev;
315 };
316
317
318
319
320
322 unlink();
323 return;
324 }
325
326
328 unlink();
329}
330
331void TimerGroup::removeTimer(Timer &T) {
333
334
335 if (T.hasTriggered())
336 TimersToPrint.emplace_back(T.Time, T.Name, T.Description);
337
338 T.TG = nullptr;
339
340
342 if (T.Next)
344}
345
346void TimerGroup::addTimer(Timer &T) {
348
349
350 if (FirstTimer)
351 FirstTimer->Prev = &T.Next;
352 T.Next = FirstTimer;
353 T.Prev = &FirstTimer;
354 FirstTimer = &T;
355}
356
357void TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
358
361
362 TimeRecord Total;
363 for (const PrintRecord &Record : TimersToPrint)
364 Total += Record.Time;
365
366
367 OS << "===" << std::string(73, '-') << "===\n";
368
369 unsigned Padding = (80-Description.length())/2;
370 if (Padding > 80) Padding = 0;
371 OS.indent(Padding) << Description << '\n';
372 OS << "===" << std::string(73, '-') << "===\n";
373
374
375
376
378 OS << format(" Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
379 Total.getProcessTime(), Total.getWallTime());
380 OS << '\n';
381
382 if (Total.getUserTime())
383 OS << " ---User Time---";
384 if (Total.getSystemTime())
385 OS << " --System Time--";
386 if (Total.getProcessTime())
387 OS << " --User+System--";
388 OS << " ---Wall Time---";
389 if (Total.getMemUsed())
390 OS << " ---Mem---";
391 if (Total.getInstructionsExecuted())
392 OS << " ---Instr---";
393 OS << " --- Name ---\n";
394
395
396 for (const PrintRecord &Record : llvm::reverse(TimersToPrint)) {
397 Record.Time.print(Total, OS);
398 OS << Record.Description << '\n';
399 }
400
402 OS << "Total\n\n";
404
405 TimersToPrint.clear();
406}
407
408void TimerGroup::prepareToPrintList(bool ResetTime) {
409
410 for (Timer *T = FirstTimer; T; T = T->Next) {
411 if (->hasTriggered()) continue;
412 bool WasRunning = T->isRunning();
413 if (WasRunning)
414 T->stopTimer();
415
416 TimersToPrint.emplace_back(T->Time, T->Name, T->Description);
417
418 if (ResetTime)
419 T->clear();
420
421 if (WasRunning)
422 T->startTimer();
423 }
424}
425
427 {
428
430 prepareToPrintList(ResetAfterPrint);
431 }
432
433
434 if (!TimersToPrint.empty())
435 PrintQueuedTimers(OS);
436}
437
440 for (Timer *T = FirstTimer; T; T = T->Next)
441 T->clear();
442}
443
446
447 for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
448 TG->print(OS);
449}
450
453 for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
454 TG->clear();
455}
456
457void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R,
458 const char *suffix, double Value) {
459 constexpr auto max_digits10 = std::numeric_limits::max_digits10;
460 OS << "\t\"time." << Name << '.' << R.Name << suffix
461 << "\": " << format("%.*e", max_digits10 - 1, Value);
462}
463
466
467 prepareToPrintList(false);
468 for (const PrintRecord &R : TimersToPrint) {
469 OS << delim;
470 delim = ",\n";
471
473 printJSONValue(OS, R, ".wall", T.getWallTime());
474 OS << delim;
475 printJSONValue(OS, R, ".user", T.getUserTime());
476 OS << delim;
477 printJSONValue(OS, R, ".sys", T.getSystemTime());
478 if (T.getMemUsed()) {
479 OS << delim;
480 printJSONValue(OS, R, ".mem", T.getMemUsed());
481 }
482 if (T.getInstructionsExecuted()) {
483 OS << delim;
484 printJSONValue(OS, R, ".instr", T.getInstructionsExecuted());
485 }
486 }
487 TimersToPrint.clear();
488 return delim;
489}
490
493 for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
494 delim = TG->printJSONValues(OS, delim);
495 return delim;
496}
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
517public:
524 "track-memory",
525 cl::desc("Enable -time-passes memory tracking (this may be slow)"),
528 "sort-timers",
529 cl::desc("In the report, sort the timers in each group in wall clock"
530 " time order"),
532
537
538
539
540
543
549};
550
552
568
573
575
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
static sys::TimePoint< std::chrono::seconds > now(bool Deterministic)
static cl::opt< std::string > OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), cl::init("-"))
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
static sys::SmartMutex< true > & timerLock()
Definition Timer.cpp:559
static ManagedStatic< TimerGlobals > ManagedTimerGlobals
Definition Timer.cpp:551
static TimerGroup & defaultTimerGroup()
Definition Timer.cpp:562
static bool isTimerGlobalsConstructed()
Definition Timer.cpp:576
static std::string & libSupportInfoOutputFilename()
Definition Timer.cpp:553
static bool trackSpace()
Definition Timer.cpp:556
static SignpostEmitter & signposts()
Definition Timer.cpp:558
static bool sortTimers()
Definition Timer.cpp:557
static size_t getMemUsage()
Definition Timer.cpp:111
static void printVal(double Val, double Total, raw_ostream &OS)
Definition Timer.cpp:179
static TimerGroup * TimerGroupList
This is the global list of TimerGroups, maintained by the TimerGroup ctor/dtor and is protected by th...
Definition Timer.cpp:271
static uint64_t getCurInstructionsExecuted()
Definition Timer.cpp:117
static Name2PairMap & namedGroupedTimers()
Definition Timer.cpp:565
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Manages the emission of signposts into the recording method supported by the OS.
LLVM_ABI void endInterval(const void *O, StringRef Name)
End a signposted interval for a given object.
LLVM_ABI void startInterval(const void *O, StringRef Name)
Begin a signposted interval for a given object.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
double getUserTime() const
double getProcessTime() const
static LLVM_ABI TimeRecord getCurrentTime(bool Start=true)
Get the current time and memory usage.
Definition Timer.cpp:128
double getWallTime() const
ssize_t getMemUsed() const
double getSystemTime() const
LLVM_ABI void print(const TimeRecord &Total, raw_ostream &OS) const
Print the current time record to OS, with a breakdown showing contributions to the Total time record.
Definition Timer.cpp:186
uint64_t getInstructionsExecuted() const
cl::opt< std::string, true > InfoOutputFilename
Definition Timer.cpp:519
cl::opt< bool > SortTimers
Definition Timer.cpp:527
sys::SmartMutex< true > TimerLock
Definition Timer.cpp:533
TimerGlobals & initDeferred()
Definition Timer.cpp:544
std::string LibSupportInfoOutputFilename
Definition Timer.cpp:518
TimerGroup DefaultTimerGroup
Definition Timer.cpp:534
cl::opt< bool > TrackSpace
Definition Timer.cpp:523
std::once_flag InitDeferredFlag
Definition Timer.cpp:541
SignpostEmitter Signposts
Definition Timer.cpp:536
std::optional< Name2PairMap > NamedGroupedTimersPtr
Definition Timer.cpp:542
The TimerGroup class is used to group together related timers into a single report that is printed wh...
static LLVM_ABI void printAll(raw_ostream &OS)
This static method prints all timers.
Definition Timer.cpp:444
LLVM_ABI void print(raw_ostream &OS, bool ResetAfterPrint=false)
Print any started timers in this group, optionally resetting timers after printing them.
Definition Timer.cpp:426
static LLVM_ABI void clearAll()
Clear out all timers.
Definition Timer.cpp:451
LLVM_ABI void clear()
Clear all timers in this group.
Definition Timer.cpp:438
LLVM_ABI ~TimerGroup()
Definition Timer.cpp:300
static LLVM_ABI void * acquireTimerGlobals()
This makes the timer globals unmanaged, and lets the user manage the lifetime.
Definition Timer.cpp:574
static LLVM_ABI const char * printAllJSONValues(raw_ostream &OS, const char *delim)
Prints all timers as JSON key/value pairs.
Definition Timer.cpp:491
LLVM_ABI const char * printJSONValues(raw_ostream &OS, const char *delim)
Definition Timer.cpp:464
static LLVM_ABI void constructForStatistics()
Ensure global objects required for statistics printing are initialized.
Definition Timer.cpp:570
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
LLVM_ABI void yieldTo(Timer &)
Stop the timer and start another timer.
Definition Timer.cpp:174
LLVM_ABI ~Timer()
Definition Timer.cpp:106
LLVM_ABI void stopTimer()
Stop the timer.
Definition Timer.cpp:159
LLVM_ABI void init(StringRef TimerName, StringRef TimerDescription)
Definition Timer.cpp:92
LLVM_ABI void clear()
Clear the timer state.
Definition Timer.cpp:169
const std::string & getName() const
Timer(StringRef TimerName, StringRef TimerDescription)
LLVM_ABI void startTimer()
Start the timer running.
Definition Timer.cpp:150
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
static LLVM_ABI void GetTimeUsage(TimePoint<> &elapsed, std::chrono::nanoseconds &user_time, std::chrono::nanoseconds &sys_time)
This static function will set user_time to the amount of CPU time spent in user (non-kernel) mode and...
static LLVM_ABI size_t GetMallocUsage()
Return process memory usage.
SmartMutex - A mutex with a compile time constant parameter that indicates whether this mutex should ...
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
@ OF_Append
The file should be opened in append mode.
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::unique_ptr< raw_ostream > CreateInfoOutputFile()
Return a stream to print our output on.
Definition Timer.cpp:66
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
void initTimerOptions()
Definition Timer.cpp:569
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr Next
@ Enabled
Convert any .debug_str_offsets tables to DWARF64 if needed.
LLVM_ABI NamedRegionTimer(StringRef Name, StringRef Description, StringRef GroupName, StringRef GroupDescription, bool Enabled=true)
Definition Timer.cpp:252
static LLVM_ABI TimerGroup & getNamedTimerGroup(StringRef GroupName, StringRef GroupDescription)
Definition Timer.cpp:260