tlx
Loading...
Searching...
No Matches
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 std::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
44MultiTimer::MultiTimer(const MultiTimer&) = default;
48
49MultiTimer::~MultiTimer() = default;
50
52 std::uint32_t hash = hash_djb2(name);
53 for (size_t i = 0; i < timers_.size(); ++i) {
54 if (timers_[i].hash == hash && strcmp(timers_[i].name, name) == 0)
55 return timers_[i];
56 }
57 Entry new_entry;
58 new_entry.hash = hash;
59 new_entry.name = name;
60 new_entry.duration = std::chrono::duration<double>::zero();
61 timers_.emplace_back(new_entry);
62 return timers_.back();
63}
64
65void MultiTimer::start(const char* timer) {
66 tlx_die_unless(timer);
67 std::uint32_t hash = hash_djb2(timer);
68 if (running_ && hash == running_hash_ && strcmp(running_, timer) == 0) {
69 static bool warning_shown = false;
70 if (!warning_shown) {
71 TLX_LOG1 << "MultiTimer: trying to start timer "
72 << timer << " twice!";
73 TLX_LOG1 << "MultiTimer: multi-threading is not supported, "
74 << "use .add()";
75 warning_shown = true;
76 }
77 }
78 stop();
79 running_ = timer;
80 running_hash_ = hash;
81}
82
84 auto new_time_point = std::chrono::high_resolution_clock::now();
85 if (running_) {
87 e.duration += new_time_point - time_point_;
88 total_duration_ += new_time_point - time_point_;
89 }
90 time_point_ = new_time_point;
91 running_ = nullptr;
92 running_hash_ = 0;
93}
94
96 timers_.clear();
97 total_duration_ = std::chrono::duration<double>::zero();
98}
99
100const char* MultiTimer::running() const {
101 return running_;
102}
103
104double MultiTimer::get(const char* name) {
105 return find_or_create(name).duration.count();
106}
107
108double MultiTimer::total() const {
109 return total_duration_.count();
110}
111
112void MultiTimer::print(const char* info, std::ostream& os) const {
114
115 os << "TIMER info=" << info;
116 for (const Entry& timer : timers_) {
117 os << ' ' << timer.name << '=' << timer.duration.count();
118 }
119 os << " total=" << total_duration_.count() << std::endl;
120}
121
122void MultiTimer::print(const char* info) const {
123 return print(info, std::cerr);
124}
125
127 std::unique_lock<std::mutex> lock(s_timer_add_mutex);
128 if (b.running_) {
129 TLX_LOG1 << "MultiTimer: trying to add running timer";
130 }
131 for (const Entry& t : b.timers_) {
132 Entry& e = find_or_create(t.name);
133 e.duration += t.duration;
134 }
136 return *this;
137}
138
140 return add(b);
141}
142
143/******************************************************************************/
144// ScopedMultiTimerSwitch
145
147 MultiTimer& timer, const char* new_timer)
148 : timer_(timer), previous_(timer.running()) {
149 timer_.start(new_timer);
150}
151
154}
155
156/******************************************************************************/
157// ScopedMultiTimer
158
160 : base_(base) {
161 timer_.start(timer);
162}
163
165 timer_.stop();
167}
168
169} // namespace tlx
170
171/******************************************************************************/
MultiTimer can be used to measure time usage of different phases in a program or algorithm.
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.
MultiTimer()
constructor
const char * running_
currently running timer name
Entry & find_or_create(const char *name)
internal methods to find or create new timer entries
std::vector< Entry > timers_
array of timers
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
std::uint32_t running_hash_
hash of running_
void stop()
stop the currently running timer.
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
void reset()
zero timers.
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 std::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:27
#define TLX_LOG1
Definition core.hpp:145
STL namespace.
static std::mutex s_timer_add_mutex
std::chrono::duration< double > duration
duration of this timer
const char * name
reference to original string for comparison
std::uint32_t hash
hash of name for faster search