blob: e3d213bced5b00df0cf6346dc12b1653da238b2e [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//===----------------------------------------------------------------------===//
9#include "lldb/Core/Timer.h"
10
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000011#include "lldb/Host/Host.h"
12#include "lldb/Utility/Stream.h"
13
14#include "llvm/Support/ThreadLocal.h"
15
Eli Friedman88966972010-06-09 08:50:27 +000016#include <algorithm>
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000017#include <map>
18#include <mutex>
19#include <vector>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020
Eli Friedman88966972010-06-09 08:50:27 +000021#include <stdio.h>
22
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023using namespace lldb_private;
24
25#define TIMER_INDENT_AMOUNT 2
Tamas Berghammerd779da92015-10-23 10:34:29 +000026
Kate Stoneb9c1b512016-09-06 20:57:50 +000027namespace {
Pavel Labath96a3c912016-11-03 09:14:09 +000028typedef std::map<const char *, std::chrono::nanoseconds> TimerCategoryMap;
29typedef std::vector<Timer *> TimerStack;
Tamas Berghammerd779da92015-10-23 10:34:29 +000030} // end of anonymous namespace
31
Tamas Berghammer5ee6b7f2015-10-23 10:53:31 +000032std::atomic<bool> Timer::g_quiet(true);
33std::atomic<unsigned> Timer::g_display_depth(0);
Kate Stoneb9c1b512016-09-06 20:57:50 +000034static std::mutex &GetFileMutex() {
Pavel Labath96a3c912016-11-03 09:14:09 +000035 static std::mutex *g_file_mutex_ptr = new std::mutex();
Kate Stoneb9c1b512016-09-06 20:57:50 +000036 return *g_file_mutex_ptr;
Greg Clayton8e1232a2016-03-24 21:46:47 +000037}
Tamas Berghammerd779da92015-10-23 10:34:29 +000038
Kate Stoneb9c1b512016-09-06 20:57:50 +000039static std::mutex &GetCategoryMutex() {
40 static std::mutex g_category_mutex;
41 return g_category_mutex;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042}
43
Kate Stoneb9c1b512016-09-06 20:57:50 +000044static TimerCategoryMap &GetCategoryMap() {
45 static TimerCategoryMap g_category_map;
46 return g_category_map;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047}
48
Kate Stoneb9c1b512016-09-06 20:57:50 +000049static void ThreadSpecificCleanup(void *p) {
50 delete static_cast<TimerStack *>(p);
Pavel Labath061140c2016-02-01 13:29:41 +000051}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052
Kate Stoneb9c1b512016-09-06 20:57:50 +000053static TimerStack *GetTimerStackForCurrentThread() {
54 static lldb::thread_key_t g_key =
55 Host::ThreadLocalStorageCreate(ThreadSpecificCleanup);
Pavel Labath061140c2016-02-01 13:29:41 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 void *timer_stack = Host::ThreadLocalStorageGet(g_key);
58 if (timer_stack == NULL) {
59 Host::ThreadLocalStorageSet(g_key, new TimerStack);
60 timer_stack = Host::ThreadLocalStorageGet(g_key);
61 }
62 return (TimerStack *)timer_stack;
63}
64
65void Timer::SetQuiet(bool value) { g_quiet = value; }
66
67Timer::Timer(const char *category, const char *format, ...)
Pavel Labath96a3c912016-11-03 09:14:09 +000068 : m_category(category), m_total_start(std::chrono::steady_clock::now()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 TimerStack *stack = GetTimerStackForCurrentThread();
70 if (!stack)
71 return;
72
Pavel Labath96a3c912016-11-03 09:14:09 +000073 stack->push_back(this);
74 if (g_quiet && stack->size() <= g_display_depth) {
75 std::lock_guard<std::mutex> lock(GetFileMutex());
Kate Stoneb9c1b512016-09-06 20:57:50 +000076
Pavel Labath96a3c912016-11-03 09:14:09 +000077 // Indent
78 ::fprintf(stdout, "%*s", int(stack->size() - 1) * TIMER_INDENT_AMOUNT, "");
79 // Print formatted string
80 va_list args;
81 va_start(args, format);
82 ::vfprintf(stdout, format, args);
83 va_end(args);
Kate Stoneb9c1b512016-09-06 20:57:50 +000084
Pavel Labath96a3c912016-11-03 09:14:09 +000085 // Newline
86 ::fprintf(stdout, "\n");
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088}
89
Kate Stoneb9c1b512016-09-06 20:57:50 +000090Timer::~Timer() {
Pavel Labath96a3c912016-11-03 09:14:09 +000091 using namespace std::chrono;
92
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 TimerStack *stack = GetTimerStackForCurrentThread();
94 if (!stack)
95 return;
Jim Inghamf7f4f502010-11-04 23:19:21 +000096
Pavel Labath96a3c912016-11-03 09:14:09 +000097 auto stop_time = steady_clock::now();
98 auto total_dur = stop_time - m_total_start;
99 auto timer_dur = total_dur - m_child_duration;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100
Pavel Labath96a3c912016-11-03 09:14:09 +0000101 if (g_quiet && stack->size() <= g_display_depth) {
102 std::lock_guard<std::mutex> lock(GetFileMutex());
103 ::fprintf(stdout, "%*s%.9f sec (%.9f sec)\n",
104 int(stack->size() - 1) * TIMER_INDENT_AMOUNT, "",
105 duration<double>(total_dur).count(),
106 duration<double>(timer_dur).count());
107 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108
Pavel Labath96a3c912016-11-03 09:14:09 +0000109 assert(stack->back() == this);
110 stack->pop_back();
111 if (!stack->empty())
112 stack->back()->ChildDuration(total_dur);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113
Pavel Labath96a3c912016-11-03 09:14:09 +0000114 // Keep total results for each category so we can dump results.
115 {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 std::lock_guard<std::mutex> guard(GetCategoryMutex());
117 TimerCategoryMap &category_map = GetCategoryMap();
Pavel Labath96a3c912016-11-03 09:14:09 +0000118 category_map[m_category] += timer_dur;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120}
121
122void Timer::SetDisplayDepth(uint32_t depth) { g_display_depth = depth; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123
124/* binary function predicate:
125 * - returns whether a person is less than another person
126 */
127static bool
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128CategoryMapIteratorSortCriterion(const TimerCategoryMap::const_iterator &lhs,
129 const TimerCategoryMap::const_iterator &rhs) {
130 return lhs->second > rhs->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000131}
132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133void Timer::ResetCategoryTimes() {
134 std::lock_guard<std::mutex> guard(GetCategoryMutex());
135 TimerCategoryMap &category_map = GetCategoryMap();
136 category_map.clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000137}
138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139void Timer::DumpCategoryTimes(Stream *s) {
140 std::lock_guard<std::mutex> guard(GetCategoryMutex());
141 TimerCategoryMap &category_map = GetCategoryMap();
142 std::vector<TimerCategoryMap::const_iterator> sorted_iterators;
143 TimerCategoryMap::const_iterator pos, end = category_map.end();
144 for (pos = category_map.begin(); pos != end; ++pos) {
145 sorted_iterators.push_back(pos);
146 }
147 std::sort(sorted_iterators.begin(), sorted_iterators.end(),
148 CategoryMapIteratorSortCriterion);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 const size_t count = sorted_iterators.size();
151 for (size_t i = 0; i < count; ++i) {
Pavel Labath96a3c912016-11-03 09:14:09 +0000152 const auto timer = sorted_iterators[i]->second;
153 s->Printf("%.9f sec for %s\n", std::chrono::duration<double>(timer).count(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 sorted_iterators[i]->first);
155 }
Eli Friedman88966972010-06-09 08:50:27 +0000156}