190792Sgshapiro//===- Timer.cpp ----------------------------------------------------------===//
2363466Sgshapiro//
390792Sgshapiro// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
490792Sgshapiro// See https://llvm.org/LICENSE.txt for license information.
590792Sgshapiro// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
690792Sgshapiro//
790792Sgshapiro//===----------------------------------------------------------------------===//
890792Sgshapiro
990792Sgshapiro#include "lld/Common/Timer.h"
1090792Sgshapiro#include "lld/Common/ErrorHandler.h"
1190792Sgshapiro#include "llvm/Support/Format.h"
1290792Sgshapiro
1390792Sgshapirousing namespace lld;
1490792Sgshapirousing namespace llvm;
1590792Sgshapiro
1690792SgshapiroScopedTimer::ScopedTimer(Timer &t) : t(&t) { t.start(); }
1790792Sgshapiro
1890792Sgshapirovoid ScopedTimer::stop() {
1990792Sgshapiro  if (!t)
2090792Sgshapiro    return;
2190792Sgshapiro  t->stop();
2290792Sgshapiro  t = nullptr;
2390792Sgshapiro}
2490792Sgshapiro
2590792SgshapiroScopedTimer::~ScopedTimer() { stop(); }
2690792Sgshapiro
2790792SgshapiroTimer::Timer(llvm::StringRef name) : name(name), parent(nullptr) {}
2890792SgshapiroTimer::Timer(llvm::StringRef name, Timer &parent)
2990792Sgshapiro    : name(name), parent(&parent) {}
3090792Sgshapiro
3190792Sgshapirovoid Timer::start() {
3290792Sgshapiro  if (parent && total.count() == 0)
3390792Sgshapiro    parent->children.push_back(this);
3490792Sgshapiro  startTime = std::chrono::high_resolution_clock::now();
3590792Sgshapiro}
3690792Sgshapiro
3790792Sgshapirovoid Timer::stop() {
3890792Sgshapiro  total += (std::chrono::high_resolution_clock::now() - startTime);
3990792Sgshapiro}
4090792Sgshapiro
4190792SgshapiroTimer &Timer::root() {
4290792Sgshapiro  static Timer rootTimer("Total Link Time");
4390792Sgshapiro  return rootTimer;
4490792Sgshapiro}
45363466Sgshapiro
4690792Sgshapirovoid Timer::print() {
47223067Sgshapiro  double totalDuration = static_cast<double>(root().millis());
48223067Sgshapiro
49223067Sgshapiro  // We want to print the grand total under all the intermediate phases, so we
50363466Sgshapiro  // print all children first, then print the total under that.
51363466Sgshapiro  for (const auto &child : children)
5290792Sgshapiro    child->print(1, totalDuration);
5390792Sgshapiro
54363466Sgshapiro  message(std::string(49, '-'));
55363466Sgshapiro
56266527Sgshapiro  root().print(0, root().millis(), false);
5790792Sgshapiro}
5890792Sgshapiro
5990792Sgshapirodouble Timer::millis() const {
6090792Sgshapiro  return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
6190792Sgshapiro             total)
6290792Sgshapiro      .count();
6390792Sgshapiro}
6490792Sgshapiro
6590792Sgshapirovoid Timer::print(int depth, double totalDuration, bool recurse) const {
66363466Sgshapiro  double p = 100.0 * millis() / totalDuration;
6790792Sgshapiro
6890792Sgshapiro  SmallString<32> str;
69363466Sgshapiro  llvm::raw_svector_ostream stream(str);
7090792Sgshapiro  std::string s = std::string(depth * 2, ' ') + name + std::string(":");
7190792Sgshapiro  stream << format("%-30s%5d ms (%5.1f%%)", s.c_str(), (int)millis(), p);
7290792Sgshapiro
7390792Sgshapiro  message(str);
7490792Sgshapiro
7590792Sgshapiro  if (recurse) {
7690792Sgshapiro    for (const auto &child : children)
77363466Sgshapiro      child->print(depth + 1, totalDuration);
78363466Sgshapiro  }
79363466Sgshapiro}
80363466Sgshapiro