tlx
multi_timer.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 * tlx/multi_timer.cpp
3 *
4 * Part of tlx - http://panthema.net/tlx
5 *
6 * Copyright (C) 2018-2019 Timo Bingmann <tb@panthema.net>
7 *
8 * All rights reserved. Published under the Boost Software License, Version 1.0
9 ******************************************************************************/
10
11#include <tlx/multi_timer.hpp>
12
13#include <iostream>
14#include <mutex>
15
16#include <tlx/die/core.hpp>
17#include <tlx/logger/core.hpp>
19
20namespace tlx {
21
22static std::mutex s_timer_add_mutex;
23
24/******************************************************************************/
25// MultiTimer::Entry
26
28 //! hash of name for faster search
29 uint32_t hash;
30 //! reference to original string for comparison
31 const char* name;
32 //! duration of this timer
33 std::chrono::duration<double> duration;
34};
35
36/******************************************************************************/
37// MultiTimer
38
40 : total_duration_(std::chrono::duration<double>::zero()),
41 running_(nullptr),
42 running_hash_(0)
43{ }
44
45MultiTimer::MultiTimer(const MultiTimer&) = default;
49
50MultiTimer::~MultiTimer() = default;
51
53 uint32_t hash = hash_djb2(name);
54 for (size_t i = 0; i < timers_.size(); ++i) {
55 if (timers_[i].hash == hash && strcmp(timers_[i].name, name) == 0)
56 return timers_[i];
57 }
58 Entry new_entry;
59 new_entry.hash = hash;
60 new_entry.name = name;
61 new_entry.duration = std::chrono::duration<double>::zero();
62 timers_.emplace_back(new_entry);
63 return timers_.back();
64}
65
66void MultiTimer::start(const char* timer) {
67 tlx_die_unless(timer);
68 uint32_t hash = hash_djb2(timer);
69 if (running_ && hash == running_hash_ && strcmp(running_, timer) == 0) {
70 static bool warning_shown = false;
71 if (!warning_shown) {
72 TLX_LOG1 << "MultiTimer: trying to start timer "
73 << timer << " twice!";
74 TLX_LOG1 << "MultiTimer: multi-threading is not supported, "
75 << "use .add()";
76 warning_shown = true;
77 }
78 }
79 stop();
80 running_ = timer;
81 running_hash_ = hash;
82}
83
85 auto new_time_point = std::chrono::high_resolution_clock::now();
86 if (running_) {
88 e.duration += new_time_point - time_point_;
89 total_duration_ += new_time_point - time_point_;
90 }
91 time_point_ = new_time_point;
92 running_ = nullptr;
93 running_hash_ = 0;
94}
95
97 timers_.clear();
98 total_duration_ = std::chrono::duration<double>::zero();
99}
100
101const char* MultiTimer::running() const {
102 return running_;
103}
104
105double MultiTimer::get(const char* name) {
106 return find_or_create(name).duration.count();
107}
108
109double MultiTimer::total() const {
110 return total_duration_.count();
111}
112
113void MultiTimer::print(const char* info, std::ostream& os) const {
115
116 os << "TIMER info=" << info;
117 for (const Entry& timer : timers_) {
118 os << ' ' << timer.name << '=' << timer.duration.count();
119 }
120 os << " total=" << total_duration_.count() << std::endl;
121}
122
123void MultiTimer::print(const char* info) const {
124 return print(info, std::cerr);
125}
126
128 std::unique_lock<std::mutex> lock(s_timer_add_mutex);
129 if (b.running_) {
130 TLX_LOG1 << "MultiTimer: trying to add running timer";
131 }
132 for (const Entry& t : b.timers_) {
133 Entry& e = find_or_create(t.name);
134 e.duration += t.duration;
135 }
137 return *this;
138}
139
141 return add(b);
142}
143
144/******************************************************************************/
145// ScopedMultiTimerSwitch
146
148 MultiTimer& timer, const char* new_timer)
149 : timer_(timer), previous_(timer.running()) {
150 timer_.start(new_timer);
151}
152
155}
156
157/******************************************************************************/
158// ScopedMultiTimer
159
161 : base_(base) {
162 timer_.start(timer);
163}
164
166 timer_.stop();
168}
169
170} // namespace tlx
171
172/******************************************************************************/
MultiTimer can be used to measure time usage of different phases in a program or algorithm.
Definition: multi_timer.hpp:37
void print(const char *info, std::ostream &os) const
print all timers as a TIMER line to os
void start(const char *timer)
start new timer phase, stop the currently running one.
Definition: multi_timer.cpp:66
MultiTimer()
constructor
Definition: multi_timer.cpp:39
const char * running_
currently running timer name
Definition: multi_timer.hpp:95
Entry & find_or_create(const char *name)
internal methods to find or create new timer entries
Definition: multi_timer.cpp:52
std::vector< Entry > timers_
array of timers
Definition: multi_timer.hpp:89
uint32_t running_hash_
hash of running_
Definition: multi_timer.hpp:97
MultiTimer & operator+=(const MultiTimer &b)
add all timers from another, internally holds a global mutex lock, because this is used to add thread...
~MultiTimer()
destructor
std::chrono::duration< double > total_duration_
total duration
Definition: multi_timer.hpp:92
void stop()
stop the currently running timer.
Definition: multi_timer.cpp:84
const char * running() const
return name of currently running timer.
MultiTimer & add(const MultiTimer &b)
add all timers from another, internally holds a global mutex lock, because this is used to add thread...
MultiTimer & operator=(const MultiTimer &)
default assignment operator
double get(const char *timer)
return timer duration in seconds of timer.
std::chrono::time_point< std::chrono::high_resolution_clock > time_point_
start of currently running timer name
Definition: multi_timer.hpp:99
void reset()
zero timers.
Definition: multi_timer.cpp:96
double total() const
return total duration of all timers.
~ScopedMultiTimerSwitch()
change back timer to previous timer.
MultiTimer & timer_
reference to MultiTimer
const char * previous_
previous timer, used to switch back to on destruction
ScopedMultiTimerSwitch(MultiTimer &timer, const char *new_timer)
construct and timer to switch to
MultiTimer & base_
reference to base timer
~ScopedMultiTimer()
change back timer to previous timer.
ScopedMultiTimer(MultiTimer &base, const char *timer)
construct and change timer to tm
MultiTimer timer_
contained independent timer
#define tlx_die_unless(X)
Check condition X and die miserably if false.
Definition: core.hpp:65
static uint32_t hash_djb2(const unsigned char *str)
Simple, fast, but "insecure" string hash method by Dan Bernstein from http://www.cse....
Definition: hash_djb2.hpp:26
#define TLX_LOG1
Definition: core.hpp:145
STL namespace.
static std::mutex s_timer_add_mutex
Definition: multi_timer.cpp:22
uint32_t hash
hash of name for faster search
Definition: multi_timer.cpp:29
std::chrono::duration< double > duration
duration of this timer
Definition: multi_timer.cpp:33
const char * name
reference to original string for comparison
Definition: multi_timer.cpp:31