Browse Source

bench: Fix initialization order in registration

The initialization order of global data structures in different
implementation units is undefined. Making use of this is essentially
gambling on what the linker does, the so-called [Static initialization
order fiasco](https://isocpp.org/wiki/faq/ctors#static-init-order).

In this case it apparently worked on Linux but failed on OpenBSD and
FreeBSD.

To create it on first use, make the registration structure local to
a function.

Fixes #8910.
0.14
Wladimir J. van der Laan 8 years ago
parent
commit
29c53289a9
  1. 16
      src/bench/bench.cpp
  2. 3
      src/bench/bench.h

16
src/bench/bench.cpp

@ -9,7 +9,10 @@ @@ -9,7 +9,10 @@
#include <iomanip>
#include <sys/time.h>
std::map<std::string, benchmark::BenchFunction> benchmark::BenchRunner::benchmarks;
benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() {
static std::map<std::string, benchmark::BenchFunction> benchmarks_map;
return benchmarks_map;
}
static double gettimedouble(void) {
struct timeval tv;
@ -19,7 +22,7 @@ static double gettimedouble(void) { @@ -19,7 +22,7 @@ static double gettimedouble(void) {
benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func)
{
benchmarks.insert(std::make_pair(name, func));
benchmarks().insert(std::make_pair(name, func));
}
void
@ -29,12 +32,9 @@ benchmark::BenchRunner::RunAll(double elapsedTimeForOne) @@ -29,12 +32,9 @@ benchmark::BenchRunner::RunAll(double elapsedTimeForOne)
std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << ","
<< "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n";
for (std::map<std::string,benchmark::BenchFunction>::iterator it = benchmarks.begin();
it != benchmarks.end(); ++it) {
State state(it->first, elapsedTimeForOne);
benchmark::BenchFunction& func = it->second;
func(state);
for (const auto &p: benchmarks()) {
State state(p.first, elapsedTimeForOne);
p.second(state);
}
perf_fini();
}

3
src/bench/bench.h

@ -63,7 +63,8 @@ namespace benchmark { @@ -63,7 +63,8 @@ namespace benchmark {
class BenchRunner
{
static std::map<std::string, BenchFunction> benchmarks;
typedef std::map<std::string, BenchFunction> BenchmarkMap;
static BenchmarkMap &benchmarks();
public:
BenchRunner(std::string name, BenchFunction func);

Loading…
Cancel
Save