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 (T.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

341 *T.Prev = T.Next;

342 if (T.Next)

343 T.Next->Prev = T.Prev;

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 (T->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