forked from vmware/concord-bft
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTimer.h
136 lines (115 loc) · 3.48 KB
/
Timer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Concord
//
// Copyright (c) 2018 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache 2.0 license (the "License").
// You may not use this product except in compliance with the Apache 2.0 License.
//
// This product may include a number of subcomponents with separate copyright
// notices and license terms. Your use of these subcomponents is subject to the
// terms and conditions of the subcomponent's license, as noted in the
// LICENSE file.
#pragma once
#include <chrono>
#include <string>
#include "XAssert.h"
using std::chrono::microseconds;
/**
* To be used as:
* {
* ScopedTimer t(std::cout, "My code took ");
* mycode();
* }
*/
class ScopedTimer {
private:
typedef std::chrono::high_resolution_clock theclock;
std::chrono::time_point<theclock> beginning;
std::ostream& out;
std::string prefix;
const char* suffix;
public:
ScopedTimer(std::ostream& out, const std::string& prefix = "", const char* suffix = "\n")
: beginning(theclock::now()), out(out), prefix(prefix), suffix(suffix) {}
~ScopedTimer() {
microseconds mus = std::chrono::duration_cast<microseconds>(theclock::now() - beginning);
out << prefix << mus.count() << " microseconds" << suffix << std::flush;
}
};
/**
* To be used as:
*
* ManualTimer t;
* mycode();
* microseconds duration = t.stop();
*
* Or as:
*
* ManualTimer t;
* mycode1();
* microseconds duration1 = t.restart();
* mycode2();
* microseconds duration 2= t.restart();
* // and so on...
*/
class ManualTimer {
private:
typedef std::chrono::high_resolution_clock theclock;
std::chrono::time_point<theclock> beginning;
public:
ManualTimer() : beginning(theclock::now()) {}
microseconds restart() {
microseconds mus = std::chrono::duration_cast<microseconds>(theclock::now() - beginning);
beginning = theclock::now();
return mus;
}
microseconds stop() const { return std::chrono::duration_cast<microseconds>(theclock::now() - beginning); }
};
/**
* To be used for timing multiple pieces of code in a loop:
*
* AveragingTimer c1, c2;
* for(int i = 0; i < numLaps; i++) {
* c1.startLap();
* mycode1();
* c1.endLap();
*
* c2.startLap();
* mycode2();
* c2.endLap();
* }
*
* std::cout << "mycode1() average lap time: " << c1.averageLapTime() << std::endl;
* std::cout << "mycode2() average lap time: " << c2.averageLapTime() << std::endl;
*/
class AveragingTimer {
private:
typedef std::chrono::high_resolution_clock theclock;
std::chrono::time_point<theclock> beginning;
microseconds total;
unsigned long iters;
bool started;
std::string name;
private:
friend std::ostream& operator<<(std::ostream& out, const AveragingTimer& t);
public:
AveragingTimer(const std::string& name = "some timer") : total(0), iters(0), started(false), name(name) {}
public:
void startLap() {
assertFalse(started);
started = true;
beginning = theclock::now();
}
const std::string& getName() const { return name; }
microseconds endLap() {
microseconds duration = std::chrono::duration_cast<microseconds>(theclock::now() - beginning);
total += duration;
iters++;
assertTrue(started); // Do this after timing, to not slow down anything.
started = false;
return duration;
}
unsigned long numIterations() const { return iters; }
microseconds::rep totalLapTime() const { return total.count(); }
microseconds::rep averageLapTime() const { return total.count() / static_cast<microseconds::rep>(iters); }
};