netxsimdg
Loading...
Searching...
No Matches
Timer.cpp
Go to the documentation of this file.
1
8#include "include/Timer.hpp"
9
10#include "include/Chrono.hpp"
11#include <chrono>
12#include <ctime>
13#include <map>
14#include <regex>
15#include <sstream>
16#include <string>
17
18namespace Nextsim {
19// Static main clock
20Timer Timer::main("main");
21
23 : Timer("")
24{
25}
26
27Timer::Timer(const Key& baseTimerName)
28 : root()
29 , current(&root)
30{
31 root.name = baseTimerName;
32 root.tick();
33}
34
35void Timer::tick(const Timer::Key& timerName)
36{
37 // Descend to the next child node, creating it if necessary
38 TimerNode* parent = current;
39 current = &current->childNodes[timerName];
40 // redundant assignment, except when a new node has been created above.
41 current->name = timerName;
42 current->parent = parent;
43
44 // Mark the time, ticks and run status of the node
45 current->tick();
46}
47
48void Timer::tock(const std::string& timerName) { tock(); }
49
51{
52 // Calculate the durations and stop running
53 current->tock();
54 // Ascend to the parent
55 current = current->parent;
56}
57
58void Timer::TimerNode::tick() { timeKeeper.start(); }
59
60void Timer::TimerNode::tock() { timeKeeper.stop(); }
61// TODO: implement lap and elapsed
62double Timer::lap(const Key& timerName) const { return 0; }
63double Timer::elapsed(const Key& timerName) const { return 0; }
64
66 const TimerPath& path, WallTimeDuration wallAdd, CpuTimeDuration cpuAdd, int ticksAdd)
67{
68 // Descend the given path
69 TimerNode& cursor = root;
70 for (auto& nodeName : path) {
71 cursor = cursor.childNodes[nodeName];
72 }
73 cursor.timeKeeper.extraWallTime(wallAdd);
74 cursor.timeKeeper.extraCpuTime(cpuAdd);
75 cursor.timeKeeper.extraTicks(ticksAdd);
76}
77
78Timer::TimerPath Timer::currentTimerNodePath() const
79{
80 TimerPath path;
81 TimerNode* cursor = current;
82 while (cursor != &root) {
83 path.push_front(cursor->name);
84 cursor = cursor->parent;
85 }
86 return path;
87}
88
89Timer::TimerPath Timer::pathToFirstMatch(const Key& timerName) const
90{
91 return root.searchDescendants(timerName);
92}
93
94std::ostream& Timer::report(const Key& timerName, std::ostream& os) const
95{
96 return report(pathToFirstMatch(timerName), os);
97}
98
99std::ostream& Timer::report(std::ostream& os) const { return root.reportAll(os, ""); }
100
101std::ostream& Timer::report(const TimerPath& path, std::ostream& os) const
102{
103 const TimerNode* cursor = &root;
104 for (auto& element : path) {
105 cursor = &cursor->childNodes.at(element);
106 }
107 return cursor->report(os, "");
108}
109
111{
112 root.childNodes.clear();
113 root.timeKeeper.reset();
114 current = &root;
115 root.tick();
116}
117
118Timer::TimerNode::TimerNode()
119 : parent(nullptr)
120{
121}
122
123Timer::TimerPath Timer::TimerNode::searchDescendants(const Key& timerName) const
124{
125 TimerPath path;
126 for (auto& children : childNodes) {
127 if (children.first == timerName) {
128 path.push_front(children.first);
129 } else if (!children.second.searchDescendants(timerName).empty()) {
130 path.push_front(name);
131 }
132 }
133 return path;
134}
135
136inline int msCountFromWall(const Timer::WallTimeDuration& wall)
137{
138 return std::chrono::duration_cast<std::chrono::microseconds>(wall).count();
139}
140
141std::ostream& Timer::TimerNode::report(std::ostream& os, const std::string& prefix) const
142{
143 os << prefix;
144 // Get the wall time in seconds
145 WallTimeDuration wallTimeNow = timeKeeper.wallTime();
146 CpuTimeDuration cpuTimeNow = timeKeeper.cpuTime();
147
148 double pcParentWall;
149 double pcParentCpu;
150 if (parent) {
151 WallTimeDuration wallTimeParent = parent->timeKeeper.wallTime();
152 CpuTimeDuration cpuTimeParent = parent->timeKeeper.cpuTime();
153 pcParentWall = msCountFromWall(wallTimeNow) * 100. / msCountFromWall(wallTimeParent);
154 pcParentCpu = cpuTimeNow * 100. / cpuTimeParent;
155 } else {
156 pcParentWall = 100;
157 pcParentCpu = 100;
158 }
159
160 double wallSeconds = msCountFromWall(wallTimeNow) * 1e-6;
161
162 os << name << ": ticks = " << timeKeeper.ticks();
163 os << " wall time " << wallSeconds << " s"
164 << " (" << pcParentWall << "% of parent)";
165 os << " cpu time " << cpuTimeNow << " s"
166 << " (" << pcParentCpu << "% of parent)";
167 os << " " << timeKeeper.ticks() << " activations (" << 1e3 * wallSeconds / timeKeeper.ticks()
168 << " ms per call)";
169 if (timeKeeper.running())
170 os << "(running)";
171 return os;
172}
173
174static std::string branch = "├";
175static std::string spc = " ";
176static std::string cont = "│";
177static std::string last = "└";
178
179std::string extendPrefix(const std::string& prefix)
180{
181 std::string newPrefix = std::regex_replace(prefix, std::regex(branch), cont);
182 return std::regex_replace(newPrefix, std::regex(last), spc);
183}
184
185std::ostream& Timer::TimerNode::reportAll(std::ostream& os, const std::string& prefix) const
186{
187 report(os, prefix);
188 os << std::endl;
189
190 int nNodes = childNodes.size();
191 int iNode = 0;
192
193 for (auto& child : childNodes) {
194 std::string lastBranch = (++iNode == nNodes) ? last : branch;
195 child.second.reportAll(os, extendPrefix(prefix) + lastBranch);
196 }
197 return os;
198}
199}
200
201std::ostream& operator<<(std::ostream& os, const Nextsim::Timer& tim) { return tim.report(os); }
void extraWallTime(const WallTimeDuration &extraTime)
Adds an externally determined increment to the wall clock.
Definition Chrono.hpp:109
void reset()
Resets all of the chronometer counters.
Definition Chrono.hpp:50
void extraCpuTime(const CpuTimeDuration &extraTime)
Adds an externally determined increment to the CPU clock.
Definition Chrono.hpp:103
void extraTicks(int extraTicks)
Adds an externally determined increment to the activation count.
Definition Chrono.hpp:116
void start()
Starts the timer.
Definition Chrono.hpp:77
A class for a hierarchical timer functions.
Definition Timer.hpp:23
void additionalTime(const TimerPath &path, WallTimeDuration additionalWall, CpuTimeDuration additionalCpu, int additionalTicks)
Adds an additional time increment to a timer.
Definition Timer.cpp:65
double elapsed(const Key &timerName) const
Returns the elapsed time.
Definition Timer.cpp:63
void tock()
Stop the last timer to be started.
Definition Timer.cpp:50
std::ostream & report(const Key &timerName, std::ostream &os) const
Prints the status of a named timer to an ostream.
Definition Timer.cpp:94
void tick(const Key &timerName)
Starts a named timer.
Definition Timer.cpp:35
Timer()
Creates a Timer with an unnamed root node.
Definition Timer.cpp:22
double lap(const Key &timerName) const
Returns the elapsed time without stopping the timer.
Definition Timer.cpp:62
void reset()
Deletes all timers except the root, which is reset.
Definition Timer.cpp:110
TimerPath currentTimerNodePath() const
Returns the timer path to the currently running timer.
Definition Timer.cpp:78
static Timer main
Static timer for general use.
Definition Timer.hpp:109