forked from igl42/cpp_software_design
-
Notifications
You must be signed in to change notification settings - Fork 0
/
G29_Bridge_Performance.cpp
151 lines (119 loc) · 4.4 KB
/
G29_Bridge_Performance.cpp
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**************************************************************************************************
*
* \file G29_Bridge_Performance.cpp
* \brief Guideline 29: Be Aware of Bridge Performance Gains and Losses
*
* Copyright (C) 2022 Klaus Iglberger - All Rights Reserved
*
* This file is part of the supplemental material for the O'Reilly book "C++ Software Design"
* (https://www.oreilly.com/library/view/c-software-design/9781098113155/).
*
* Copy-and-paste the following code into 'quick-bench.com'. Benchmark the time to determine
* the oldest person contained in a std::vector of Persons.
*
**************************************************************************************************/
#include <memory>
#include <numeric>
#include <random>
#include <string>
#include <vector>
//---- Benchmark configuration --------------------------------------------------------------------
constexpr size_t size( 10000 ); // Size of the generated container
constexpr size_t iterations( 10 ); // Number of benchmark iterations
#define BENCHMARK_PERSON1 1 // No bridge: all data members in class
#define BENCHMARK_PERSON2 1 // Complete bridge: all data members behind pimpl
#define BENCHMARK_PERSON3 1 // Partial bridge: only rarely used data members behind pimpl
//---- Random Number Setup ------------------------------------------------------------------------
std::random_device rd{};
const unsigned int seed( rd() );
std::mt19937 rng{};
std::uniform_int_distribution<int> dist( 1957, 2004 );
int get_random_year_of_birth()
{
return dist( rd );
}
//---- Person implementations ---------------------------------------------------------------------
struct Person1
{
std::string forename{ "Homer" };
std::string surname{ "Simpson" };
std::string address{ "712 Red Bark Lane" };
std::string zip{ "89011" };
std::string city{ "Henderson" };
std::string state{ "Nevada" };
int year_of_birth{ get_random_year_of_birth() };
};
struct Person2
{
struct Pimpl {
std::string forename{ "Homer" };
std::string surname{ "Simpson" };
std::string address{ "712 Red Bark Lane" };
std::string zip{ "89011" };
std::string city{ "Henderson" };
std::string state{ "Nevada" };
int year_of_birth{ get_random_year_of_birth() };
};
std::unique_ptr<Pimpl> pimpl{ new Pimpl{} };
};
struct Person3
{
std::string forename{ "Homer" };
std::string surname{ "Simpson" };
int year_of_birth{ get_random_year_of_birth() };
struct Pimpl {
std::string address{ "712 Red Bark Lane" };
std::string zip{ "89011" };
std::string city{ "Henderson" };
std::string state{ "Nevada" };
};
std::unique_ptr<Pimpl> pimpl{ new Pimpl{} };
};
//---- Benchmark for Person1 ----------------------------------------------------------------------
static void determineOldestPerson1(benchmark::State& state)
{
std::vector<Person1> persons( size );
for( auto _ : state )
{
benchmark::DoNotOptimize(
std::min_element( begin(persons), end(persons), []( auto const& p1, auto const& p2 ){
return p1.year_of_birth < p2.year_of_birth;
} )
);
}
}
#if BENCHMARK_PERSON1
BENCHMARK(determineOldestPerson1)->Iterations(iterations);
#endif
//---- Benchmark for Person2 ----------------------------------------------------------------------
static void determineOldestPerson2(benchmark::State& state)
{
std::vector<Person2> persons( size );
for( auto _ : state )
{
benchmark::DoNotOptimize(
std::min_element( begin(persons), end(persons), []( auto const& p1, auto const& p2 ){
return p1.pimpl->year_of_birth < p2.pimpl->year_of_birth;
} )
);
}
}
#if BENCHMARK_PERSON2
BENCHMARK(determineOldestPerson2)->Iterations(iterations);
#endif
//---- Benchmark for Person3 ----------------------------------------------------------------------
static void determineOldestPerson3(benchmark::State& state)
{
std::vector<Person3> persons( size );
for( auto _ : state )
{
benchmark::DoNotOptimize(
std::min_element( begin(persons), end(persons), []( auto const& p1, auto const& p2 ){
return p1.year_of_birth < p2.year_of_birth;
} )
);
}
}
#if BENCHMARK_PERSON3
BENCHMARK(determineOldestPerson3)->Iterations(iterations);
#endif