openMSX
utils
ProfileCounters.hh
Go to the documentation of this file.
1
#ifndef PROFILECOUNTERS_HH
2
#define PROFILECOUNTERS_HH
3
4
#include "
enumerate.hh
"
5
#include <iostream>
6
7
//
8
// Quick and dirty reflection on C++ enums (in the future replace with c++23 reflexpr).
9
//
10
11
// Print an enum type as a string, for example:
12
// os << EnumTypeName<SomeEnumType>() << '\n';
13
template
<
typename
E>
struct
EnumTypeName
{};
14
// You _must_ overload 'operator<<' for all enum types for which you want this to work.
15
template
<
typename
E> std::ostream&
operator<<
(std::ostream& os,
EnumTypeName<E>
) =
delete
;
16
17
// Print an enum value as a string, for example:
18
// os << EnumValueName{myEnumValue} << '\n';
19
template
<
typename
E>
struct
EnumValueName
20
{
21
EnumValueName
(
E
e_) :
e
(e_) {}
22
E
e
;
23
};
24
// You _must_ overload 'operator<<' for all enum types for which you want this to work.
25
template
<
typename
E> std::ostream&
operator<<
(std::ostream& os,
EnumValueName<E>
evn) =
delete
;
26
27
28
29
30
// A collection of (simple) profile counters:
31
// - Counters start at zero.
32
// - An individual counter can be incremented by 1 via 'tick(<counter-id>)'.
33
// - When this 'ProfileCounters' object is destoyed it prints the value of each
34
// counter.
35
//
36
// Template parameters:
37
// - bool ENABLED:
38
// when false, the optimizer should be able to completely optimize-out all
39
// profile related code
40
// - typename ENUM:
41
// Must be a c++ enum (or enum class) which satisfies the following requirements:
42
// * The numerical values must be 0, 1, ... IOW the values must be usable as
43
// indices in an array. (This is automatically the case if you don't
44
// manually assign numeric values).
45
// * There must be an enum value with the name 'NUM' which has a numerical
46
// value equal to the number of other values in this enum. (This is
47
// automatically the case if you put 'NUM' last in the list of enum
48
// values).
49
// * You must overload the following two functions for the type 'ENUM':
50
// std::ostream& operator<<(std::ostream& os, EnumTypeName<ENUM>);
51
// std::ostream& operator<<(std::ostream& os, EnumValueName<ENUM> evn);
52
//
53
// Example usage:
54
// enum class WidgetProfileCounter {
55
// CALCULATE,
56
// INVALIDATE,
57
// NUM // must be last
58
// };
59
// std::ostream& operator<<(std::ostream& os, EnumTypeName<WidgetProfileCounter>)
60
// {
61
// return os << "WidgetProfileCounter";
62
// }
63
// std::ostream& operator<<(std::ostream& os, EnumValueName<WidgetProfileCounter> evn)
64
// {
65
// std::string_view names[size_t(WidgetProfileCounter::NUM)] = {
66
// "calculate"sv, "invalidate"sv
67
// };
68
// return os << names[size_t(evn.e)];
69
// }
70
//
71
// constexpr bool PRINT_WIDGET_PROFILE = true; // possibly depending on some #define
72
//
73
// struct Widget : private ProfileCounters<PRINT_WIDGET_PROFILE, WidgetProfileCounter>
74
// {
75
// void calculate() {
76
// tick(WidgetProfileCounter::CALCULATE);
77
// // ...
78
// }
79
// void invalidate() {
80
// tick(WidgetProfileCounter::CALCULATE);
81
// // ...
82
// }
83
// };
84
85
template
<
bool
ENABLED,
typename
ENUM>
86
class
ProfileCounters
87
{
88
public
:
89
// Print counters on destruction.
90
~ProfileCounters
() {
91
std::cout <<
"-- Profile counters: "
<<
EnumTypeName<ENUM>
() <<
" -- "
<<
static_cast<
void
*
>
(
this
) <<
'\n'
;
92
for
(
auto
[i,
count
] :
enumerate
(counters)) {
93
std::cout <<
EnumValueName
{ENUM(i)} <<
": "
<<
count
<<
'\n'
;
94
}
95
}
96
97
// Increment
98
void
tick
(ENUM
e
)
const
{
99
++counters[size_t(
e
)];
100
}
101
102
private
:
103
static
constexpr
auto
NUM = size_t(
ENUM::NUM
);
// value 'ENUM::NUM' must exist
104
mutable
unsigned
counters[NUM] = {};
105
};
106
107
108
// Specialization for when profiling is disabled.
109
// This class is simple enough so that it can be completely optimized away.
110
template
<
typename
ENUM>
111
class
ProfileCounters
<false, ENUM>
112
{
113
public
:
114
void
tick
(ENUM)
const
{
/*nothing*/
}
115
};
116
117
#endif
operator<<
std::ostream & operator<<(std::ostream &os, EnumTypeName< E >)=delete
ProfileCounters< false, ENUM >::tick
void tick(ENUM) const
Definition:
ProfileCounters.hh:114
ProfileCounters
Definition:
ProfileCounters.hh:87
ProfileCounters::tick
void tick(ENUM e) const
Definition:
ProfileCounters.hh:98
ProfileCounters::~ProfileCounters
~ProfileCounters()
Definition:
ProfileCounters.hh:90
enumerate.hh
enumerate
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition:
enumerate.hh:28
LZ4::count
ALWAYS_INLINE unsigned count(const uint8_t *pIn, const uint8_t *pMatch, const uint8_t *pInLimit)
Definition:
lz4.cc:146
Math::e
constexpr double e
Definition:
Math.hh:18
openmsx::CacheLine::NUM
constexpr unsigned NUM
Definition:
CacheLine.hh:8
openmsx::E
@ E
Definition:
CPUCore.cc:200
EnumTypeName
Definition:
ProfileCounters.hh:13
EnumValueName
Definition:
ProfileCounters.hh:20
EnumValueName::e
E e
Definition:
ProfileCounters.hh:22
EnumValueName::EnumValueName
EnumValueName(E e_)
Definition:
ProfileCounters.hh:21
Generated on Sat Jun 25 2022 11:13:26 for openMSX by
1.9.1