blob: d55c9863117b9a143319ede31ff6f3a0138d449c [file] [log] [blame]
Raphael Isemann80814282020-01-24 08:23:27 +01001//===-- Timer.cpp ---------------------------------------------------------===//
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
Pavel Labath38d06322017-06-29 14:32:17 +00008#include "lldb/Utility/Timer.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +00009#include "lldb/Utility/Stream.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000010
Eli Friedman88966972010-06-09 08:50:27 +000011#include <algorithm>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000012#include <map>
13#include <mutex>
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000014#include <utility>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000015#include <vector>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000017#include <assert.h>
Reid Kleckner34312ed2020-02-26 10:34:12 -080018#include <inttypes.h>
Jonas Devlieghere672d2c12018-11-11 23:16:43 +000019#include <stdarg.h>
Eli Friedman88966972010-06-09 08:50:27 +000020#include <stdio.h>
21
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022using namespace lldb_private;
23
24#define TIMER_INDENT_AMOUNT 2
Tamas Berghammerd779da92015-10-23 10:34:29 +000025
Kate Stoneb9c1b512016-09-06 20:57:50 +000026namespace {
Pavel Labath96a3c912016-11-03 09:14:09 +000027typedef std::vector<Timer *> TimerStack;
Pavel Labathf9d16472017-05-15 13:02:37 +000028static std::atomic<Timer::Category *> g_categories;
Tamas Berghammerd779da92015-10-23 10:34:29 +000029} // end of anonymous namespace
30
Tamas Berghammer5ee6b7f2015-10-23 10:53:31 +000031std::atomic<bool> Timer::g_quiet(true);
32std::atomic<unsigned> Timer::g_display_depth(0);
Kate Stoneb9c1b512016-09-06 20:57:50 +000033static std::mutex &GetFileMutex() {
Pavel Labath96a3c912016-11-03 09:14:09 +000034 static std::mutex *g_file_mutex_ptr = new std::mutex();
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 return *g_file_mutex_ptr;
Greg Clayton8e1232a2016-03-24 21:46:47 +000036}
Tamas Berghammerd779da92015-10-23 10:34:29 +000037
Pavel Labathf8918122017-06-20 08:11:43 +000038static TimerStack &GetTimerStackForCurrentThread() {
39 static thread_local TimerStack g_stack;
40 return g_stack;
Kate Stoneb9c1b512016-09-06 20:57:50 +000041}
42
Pavel Labathf9d16472017-05-15 13:02:37 +000043Timer::Category::Category(const char *cat) : m_name(cat) {
44 m_nanos.store(0, std::memory_order_release);
Antonio Afonso78337422019-05-29 16:31:32 +000045 m_nanos_total.store(0, std::memory_order_release);
46 m_count.store(0, std::memory_order_release);
Pavel Labathf9d16472017-05-15 13:02:37 +000047 Category *expected = g_categories;
48 do {
49 m_next = expected;
50 } while (!g_categories.compare_exchange_weak(expected, this));
51}
52
Kate Stoneb9c1b512016-09-06 20:57:50 +000053void Timer::SetQuiet(bool value) { g_quiet = value; }
54
Pavel Labathf9d16472017-05-15 13:02:37 +000055Timer::Timer(Timer::Category &category, const char *format, ...)
Pavel Labath96a3c912016-11-03 09:14:09 +000056 : m_category(category), m_total_start(std::chrono::steady_clock::now()) {
Pavel Labathf8918122017-06-20 08:11:43 +000057 TimerStack &stack = GetTimerStackForCurrentThread();
Kate Stoneb9c1b512016-09-06 20:57:50 +000058
Pavel Labathf8918122017-06-20 08:11:43 +000059 stack.push_back(this);
60 if (g_quiet && stack.size() <= g_display_depth) {
Pavel Labath96a3c912016-11-03 09:14:09 +000061 std::lock_guard<std::mutex> lock(GetFileMutex());
Kate Stoneb9c1b512016-09-06 20:57:50 +000062
Pavel Labath96a3c912016-11-03 09:14:09 +000063 // Indent
Pavel Labathf8918122017-06-20 08:11:43 +000064 ::fprintf(stdout, "%*s", int(stack.size() - 1) * TIMER_INDENT_AMOUNT, "");
Pavel Labath96a3c912016-11-03 09:14:09 +000065 // Print formatted string
66 va_list args;
67 va_start(args, format);
68 ::vfprintf(stdout, format, args);
69 va_end(args);
Kate Stoneb9c1b512016-09-06 20:57:50 +000070
Pavel Labath96a3c912016-11-03 09:14:09 +000071 // Newline
72 ::fprintf(stdout, "\n");
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074}
75
Kate Stoneb9c1b512016-09-06 20:57:50 +000076Timer::~Timer() {
Pavel Labath96a3c912016-11-03 09:14:09 +000077 using namespace std::chrono;
78
Pavel Labath96a3c912016-11-03 09:14:09 +000079 auto stop_time = steady_clock::now();
80 auto total_dur = stop_time - m_total_start;
81 auto timer_dur = total_dur - m_child_duration;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082
Pavel Labathf8918122017-06-20 08:11:43 +000083 TimerStack &stack = GetTimerStackForCurrentThread();
84 if (g_quiet && stack.size() <= g_display_depth) {
Pavel Labath96a3c912016-11-03 09:14:09 +000085 std::lock_guard<std::mutex> lock(GetFileMutex());
86 ::fprintf(stdout, "%*s%.9f sec (%.9f sec)\n",
Pavel Labathf8918122017-06-20 08:11:43 +000087 int(stack.size() - 1) * TIMER_INDENT_AMOUNT, "",
Pavel Labath96a3c912016-11-03 09:14:09 +000088 duration<double>(total_dur).count(),
89 duration<double>(timer_dur).count());
90 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091
Pavel Labathf8918122017-06-20 08:11:43 +000092 assert(stack.back() == this);
93 stack.pop_back();
94 if (!stack.empty())
95 stack.back()->ChildDuration(total_dur);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096
Pavel Labath96a3c912016-11-03 09:14:09 +000097 // Keep total results for each category so we can dump results.
Pavel Labathf9d16472017-05-15 13:02:37 +000098 m_category.m_nanos += std::chrono::nanoseconds(timer_dur).count();
Antonio Afonso78337422019-05-29 16:31:32 +000099 m_category.m_nanos_total += std::chrono::nanoseconds(total_dur).count();
100 m_category.m_count++;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101}
102
103void Timer::SetDisplayDepth(uint32_t depth) { g_display_depth = depth; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104
105/* binary function predicate:
106 * - returns whether a person is less than another person
107 */
Antonio Afonso78337422019-05-29 16:31:32 +0000108namespace {
109struct Stats {
110 const char *name;
111 uint64_t nanos;
112 uint64_t nanos_total;
113 uint64_t count;
114};
115} // namespace
Pavel Labathf9d16472017-05-15 13:02:37 +0000116
Antonio Afonso78337422019-05-29 16:31:32 +0000117static bool CategoryMapIteratorSortCriterion(const Stats &lhs,
118 const Stats &rhs) {
119 return lhs.nanos > rhs.nanos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120}
121
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122void Timer::ResetCategoryTimes() {
Antonio Afonso78337422019-05-29 16:31:32 +0000123 for (Category *i = g_categories; i; i = i->m_next) {
Pavel Labathf9d16472017-05-15 13:02:37 +0000124 i->m_nanos.store(0, std::memory_order_release);
Antonio Afonso78337422019-05-29 16:31:32 +0000125 i->m_nanos_total.store(0, std::memory_order_release);
126 i->m_count.store(0, std::memory_order_release);
127 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000128}
129
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130void Timer::DumpCategoryTimes(Stream *s) {
Antonio Afonso78337422019-05-29 16:31:32 +0000131 std::vector<Stats> sorted;
Pavel Labathf9d16472017-05-15 13:02:37 +0000132 for (Category *i = g_categories; i; i = i->m_next) {
133 uint64_t nanos = i->m_nanos.load(std::memory_order_acquire);
Antonio Afonso78337422019-05-29 16:31:32 +0000134 if (nanos) {
135 uint64_t nanos_total = i->m_nanos_total.load(std::memory_order_acquire);
136 uint64_t count = i->m_count.load(std::memory_order_acquire);
137 Stats stats{i->m_name, nanos, nanos_total, count};
138 sorted.push_back(stats);
139 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 }
Pavel Labathf9d16472017-05-15 13:02:37 +0000141 if (sorted.empty())
142 return; // Later code will break without any elements.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143
Pavel Labathf9d16472017-05-15 13:02:37 +0000144 // Sort by time
Jonas Devlieghere9bbba272019-01-08 23:25:06 +0000145 llvm::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion);
Pavel Labathf9d16472017-05-15 13:02:37 +0000146
Antonio Afonso78337422019-05-29 16:31:32 +0000147 for (const auto &stats : sorted)
Richard Trieuc8f2efe2019-05-29 21:25:15 +0000148 s->Printf("%.9f sec (total: %.3fs; child: %.3fs; count: %" PRIu64
149 ") for %s\n",
Antonio Afonso78337422019-05-29 16:31:32 +0000150 stats.nanos / 1000000000., stats.nanos_total / 1000000000.,
151 (stats.nanos_total - stats.nanos) / 1000000000., stats.count,
152 stats.name);
Eli Friedman88966972010-06-09 08:50:27 +0000153}