120d35e67SDimitry Andric //===- Timer.cpp ----------------------------------------------------------===//
220d35e67SDimitry Andric //
3f1e1c239SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f1e1c239SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5f1e1c239SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
620d35e67SDimitry Andric //
720d35e67SDimitry Andric //===----------------------------------------------------------------------===//
820d35e67SDimitry Andric
920d35e67SDimitry Andric #include "lld/Common/Timer.h"
1020d35e67SDimitry Andric #include "lld/Common/ErrorHandler.h"
117fa27ce4SDimitry Andric #include "llvm/ADT/SmallString.h"
1220d35e67SDimitry Andric #include "llvm/Support/Format.h"
136f8fc217SDimitry Andric #include <ratio>
1420d35e67SDimitry Andric
1520d35e67SDimitry Andric using namespace lld;
1620d35e67SDimitry Andric using namespace llvm;
1720d35e67SDimitry Andric
ScopedTimer(Timer & t)18cfca06d7SDimitry Andric ScopedTimer::ScopedTimer(Timer &t) : t(&t) {
19cfca06d7SDimitry Andric startTime = std::chrono::high_resolution_clock::now();
20cfca06d7SDimitry Andric }
2120d35e67SDimitry Andric
stop()2220d35e67SDimitry Andric void ScopedTimer::stop() {
23f1e1c239SDimitry Andric if (!t)
2420d35e67SDimitry Andric return;
25cfca06d7SDimitry Andric t->addToTotal(std::chrono::high_resolution_clock::now() - startTime);
26f1e1c239SDimitry Andric t = nullptr;
2720d35e67SDimitry Andric }
2820d35e67SDimitry Andric
~ScopedTimer()2920d35e67SDimitry Andric ScopedTimer::~ScopedTimer() { stop(); }
3020d35e67SDimitry Andric
Timer(llvm::StringRef name)31c0981da4SDimitry Andric Timer::Timer(llvm::StringRef name) : total(0), name(std::string(name)) {}
Timer(llvm::StringRef name,Timer & parent)32c0981da4SDimitry Andric Timer::Timer(llvm::StringRef name, Timer &parent)
33c0981da4SDimitry Andric : total(0), name(std::string(name)) {
34cfca06d7SDimitry Andric parent.children.push_back(this);
3520d35e67SDimitry Andric }
3620d35e67SDimitry Andric
print()3720d35e67SDimitry Andric void Timer::print() {
38c0981da4SDimitry Andric double totalDuration = static_cast<double>(millis());
3920d35e67SDimitry Andric
4020d35e67SDimitry Andric // We want to print the grand total under all the intermediate phases, so we
4120d35e67SDimitry Andric // print all children first, then print the total under that.
42f1e1c239SDimitry Andric for (const auto &child : children)
43cfca06d7SDimitry Andric if (child->total > 0)
44f1e1c239SDimitry Andric child->print(1, totalDuration);
4520d35e67SDimitry Andric
46b60736ecSDimitry Andric message(std::string(50, '-'));
4720d35e67SDimitry Andric
48c0981da4SDimitry Andric print(0, millis(), false);
4920d35e67SDimitry Andric }
5020d35e67SDimitry Andric
millis() const5120d35e67SDimitry Andric double Timer::millis() const {
5220d35e67SDimitry Andric return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
53cfca06d7SDimitry Andric std::chrono::nanoseconds(total))
5420d35e67SDimitry Andric .count();
5520d35e67SDimitry Andric }
5620d35e67SDimitry Andric
print(int depth,double totalDuration,bool recurse) const57f1e1c239SDimitry Andric void Timer::print(int depth, double totalDuration, bool recurse) const {
58f1e1c239SDimitry Andric double p = 100.0 * millis() / totalDuration;
5920d35e67SDimitry Andric
60f1e1c239SDimitry Andric SmallString<32> str;
61f1e1c239SDimitry Andric llvm::raw_svector_ostream stream(str);
62f1e1c239SDimitry Andric std::string s = std::string(depth * 2, ' ') + name + std::string(":");
63b60736ecSDimitry Andric stream << format("%-30s%7d ms (%5.1f%%)", s.c_str(), (int)millis(), p);
6420d35e67SDimitry Andric
65f1e1c239SDimitry Andric message(str);
6620d35e67SDimitry Andric
67f1e1c239SDimitry Andric if (recurse) {
68f1e1c239SDimitry Andric for (const auto &child : children)
69cfca06d7SDimitry Andric if (child->total > 0)
70f1e1c239SDimitry Andric child->print(depth + 1, totalDuration);
7120d35e67SDimitry Andric }
7220d35e67SDimitry Andric }
73