blob: fe7787458fa6d77d35d394f2a28346682bbdee4d [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Timer.cpp -----------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Pavel Labath38d06322017-06-29 14:32:17 +00009#include "lldb/Utility/Timer.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000010#include "lldb/Utility/Stream.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000011
Eli Friedman88966972010-06-09 08:50:27 +000012#include <algorithm>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000013#include <map>
14#include <mutex>
Zachary Turner2f3df612017-04-06 21:28:29 +000015#include <utility> // for pair
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000016#include <vector>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017
Zachary Turner2f3df612017-04-06 21:28:29 +000018#include <assert.h> // for assert
19#include <stdarg.h> // for va_end, va_list, va_start
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);
45 Category *expected = g_categories;
46 do {
47 m_next = expected;
48 } while (!g_categories.compare_exchange_weak(expected, this));
49}
50
Kate Stoneb9c1b512016-09-06 20:57:50 +000051void Timer::SetQuiet(bool value) { g_quiet = value; }
52
Pavel Labathf9d16472017-05-15 13:02:37 +000053Timer::Timer(Timer::Category &category, const char *format, ...)
Pavel Labath96a3c912016-11-03 09:14:09 +000054 : m_category(category), m_total_start(std::chrono::steady_clock::now()) {
Pavel Labathf8918122017-06-20 08:11:43 +000055 TimerStack &stack = GetTimerStackForCurrentThread();
Kate Stoneb9c1b512016-09-06 20:57:50 +000056
Pavel Labathf8918122017-06-20 08:11:43 +000057 stack.push_back(this);
58 if (g_quiet && stack.size() <= g_display_depth) {
Pavel Labath96a3c912016-11-03 09:14:09 +000059 std::lock_guard<std::mutex> lock(GetFileMutex());
Kate Stoneb9c1b512016-09-06 20:57:50 +000060
Pavel Labath96a3c912016-11-03 09:14:09 +000061 // Indent
Pavel Labathf8918122017-06-20 08:11:43 +000062 ::fprintf(stdout, "%*s", int(stack.size() - 1) * TIMER_INDENT_AMOUNT, "");
Pavel Labath96a3c912016-11-03 09:14:09 +000063 // Print formatted string
64 va_list args;
65 va_start(args, format);
66 ::vfprintf(stdout, format, args);
67 va_end(args);
Kate Stoneb9c1b512016-09-06 20:57:50 +000068
Pavel Labath96a3c912016-11-03 09:14:09 +000069 // Newline
70 ::fprintf(stdout, "\n");
Kate Stoneb9c1b512016-09-06 20:57:50 +000071 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072}
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074Timer::~Timer() {
Pavel Labath96a3c912016-11-03 09:14:09 +000075 using namespace std::chrono;
76
Pavel Labath96a3c912016-11-03 09:14:09 +000077 auto stop_time = steady_clock::now();
78 auto total_dur = stop_time - m_total_start;
79 auto timer_dur = total_dur - m_child_duration;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080
Pavel Labathf8918122017-06-20 08:11:43 +000081 TimerStack &stack = GetTimerStackForCurrentThread();
82 if (g_quiet && stack.size() <= g_display_depth) {
Pavel Labath96a3c912016-11-03 09:14:09 +000083 std::lock_guard<std::mutex> lock(GetFileMutex());
84 ::fprintf(stdout, "%*s%.9f sec (%.9f sec)\n",
Pavel Labathf8918122017-06-20 08:11:43 +000085 int(stack.size() - 1) * TIMER_INDENT_AMOUNT, "",
Pavel Labath96a3c912016-11-03 09:14:09 +000086 duration<double>(total_dur).count(),
87 duration<double>(timer_dur).count());
88 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089
Pavel Labathf8918122017-06-20 08:11:43 +000090 assert(stack.back() == this);
91 stack.pop_back();
92 if (!stack.empty())
93 stack.back()->ChildDuration(total_dur);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094
Pavel Labath96a3c912016-11-03 09:14:09 +000095 // Keep total results for each category so we can dump results.
Pavel Labathf9d16472017-05-15 13:02:37 +000096 m_category.m_nanos += std::chrono::nanoseconds(timer_dur).count();
Kate Stoneb9c1b512016-09-06 20:57:50 +000097}
98
99void Timer::SetDisplayDepth(uint32_t depth) { g_display_depth = depth; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100
101/* binary function predicate:
102 * - returns whether a person is less than another person
103 */
Pavel Labathf9d16472017-05-15 13:02:37 +0000104
105typedef std::pair<const char *, uint64_t> TimerEntry;
106
107static bool CategoryMapIteratorSortCriterion(const TimerEntry &lhs,
108 const TimerEntry &rhs) {
109 return lhs.second > rhs.second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000110}
111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112void Timer::ResetCategoryTimes() {
Pavel Labathf9d16472017-05-15 13:02:37 +0000113 for (Category *i = g_categories; i; i = i->m_next)
114 i->m_nanos.store(0, std::memory_order_release);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115}
116
Kate Stoneb9c1b512016-09-06 20:57:50 +0000117void Timer::DumpCategoryTimes(Stream *s) {
Pavel Labathf9d16472017-05-15 13:02:37 +0000118 std::vector<TimerEntry> sorted;
119 for (Category *i = g_categories; i; i = i->m_next) {
120 uint64_t nanos = i->m_nanos.load(std::memory_order_acquire);
121 if (nanos)
122 sorted.push_back(std::make_pair(i->m_name, nanos));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123 }
Pavel Labathf9d16472017-05-15 13:02:37 +0000124 if (sorted.empty())
125 return; // Later code will break without any elements.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126
Pavel Labathf9d16472017-05-15 13:02:37 +0000127 // Sort by time
128 std::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion);
129
130 for (const auto &timer : sorted)
131 s->Printf("%.9f sec for %s\n", timer.second / 1000000000., timer.first);
Eli Friedman88966972010-06-09 08:50:27 +0000132}