Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions doc/benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ while the advanced callables are invoked exactly twice: once during the
estimation phase, and another time during the execution phase.

{% highlight cpp %}
NONIUS_BENCHMARK("simple", [] { return long_computation(); });
NONIUS_BENCHMARK("simple") { return long_computation(); }

NONIUS_BENCHMARK("advanced", [](nonius::chronometer meter) {
NONIUS_BENCHMARK("advanced") (nonius::chronometer meter) {
set_up();
meter.measure([] { return long_computation(); });
});
}
{% endhighlight %}

These advanced callables no longer consist entirely of user code to be measured.
Expand Down Expand Up @@ -120,19 +120,19 @@ construct and destroy objects without dynamic allocation and in a way that lets
you measure construction and destruction separately.

{% highlight cpp %}
NONIUS_BENCHMARK("construct", [](nonius::chronometer meter)
NONIUS_BENCHMARK("construct") (nonius::chronometer meter)
{
std::vector<nonius::storage_for<std::string>> storage(meter.runs());
meter.measure([&](int i) { storage[i].construct("thing"); });
})
}

NONIUS_BENCHMARK("destroy", [](nonius::chronometer meter)
NONIUS_BENCHMARK("destroy") (nonius::chronometer meter)
{
std::vector<nonius::destructable_object<std::string>> storage(meter.runs());
for(auto&& o : storage)
o.construct("thing");
meter.measure([&](int i) { storage[i].destruct(); });
})
}
{% endhighlight %}

`nonius::storage_for<T>` objects are just pieces of raw storage suitable for `T`
Expand Down Expand Up @@ -170,10 +170,10 @@ Here's an example:
{% highlight cpp %}
// may measure nothing at all by skipping the long calculation since its
// result is not used
NONIUS_BENCHMARK("no return", [] { long_calculation(); })
NONIUS_BENCHMARK("no return") { long_calculation(); }

// the result of long_calculation() is guaranteed to be computed somehow
NONIUS_BENCHMARK("with return", [] { return long_calculation(); })
NONIUS_BENCHMARK("with return") { return long_calculation(); }
{% endhighlight %}

However, there's no other form of control over the optimizer whatsoever. It is
Expand Down
5 changes: 3 additions & 2 deletions examples/example1.c++
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NONIUS_BENCHMARK("to_string(42)", []{
return std::to_string(42);
})

NONIUS_BENCHMARK("to_string(4.2)", []{
// new syntax
NONIUS_BENCHMARK("to_string(4.2)") []{
return std::to_string(4.2);
})
};
5 changes: 3 additions & 2 deletions examples/example2.c++
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ NONIUS_BENCHMARK("forward_list<long long>", [](nonius::chronometer meter) {
meter.measure([&](int i) { l.push_front(i); });
})

NONIUS_BENCHMARK("forward_list<char>", [](nonius::chronometer meter) {
// new syntax
NONIUS_BENCHMARK("forward_list<char>") [](nonius::chronometer meter) {
std::forward_list<char> l;
meter.measure([&](int i) { l.push_front(static_cast<char>(i)); });
})
};
32 changes: 28 additions & 4 deletions include/nonius/benchmark.h++
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,38 @@ namespace nonius {
}

struct benchmark_registrar {
benchmark_registry& registry;
std::string name;

benchmark_registrar(benchmark_registry& r, std::string n)
: registry(r)
, name(n)
{}

template <typename Fun>
benchmark_registrar(benchmark_registry& registry, std::string name, Fun&& registrant) {
registry.emplace_back(std::move(name), std::forward<Fun>(registrant));
benchmark_registrar const& operator+ (Fun&& registrant) const {
registry.emplace_back(name, std::forward<Fun>(registrant));
return *this;
}
};
} // namespace nonius

#define NONIUS_BENCHMARK(name, ...) \
namespace { static ::nonius::benchmark_registrar NONIUS_DETAIL_UNIQUE_NAME(benchmark_registrar) (::nonius::global_benchmark_registry(), name, __VA_ARGS__); }
#define NONIUS_BENCHMARK_OLD_(name, ...) \
namespace { \
static auto NONIUS_DETAIL_UNIQUE_NAME(benchmark_registrar) = \
::nonius::benchmark_registrar{::nonius::global_benchmark_registry(), name} + (__VA_ARGS__); \
} \
//

#define NONIUS_BENCHMARK_NEW_(name) \
static auto NONIUS_DETAIL_UNIQUE_NAME(benchmark_registrar) = \
::nonius::benchmark_registrar{::nonius::global_benchmark_registry(), name} + \
//

#define NONIUS_BENCHMARK_CHOOSE_(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28,p29,p30,p31,p32,p33,p34,p35,p36,p37,p38,p39,p40,p41,p42,p43,p44,p45,p46,p47,p48,p49,p50,p51,p52,p53,p54,p55,p56,p57,p58,p59,p60,p61,p62,p63,p64,p65,p66,p67,p68,p69,p70,p71,p72,p73,p74,p75,p76,p77,p78,p79,p80,p81,p82,p83,p84,p85,p86,p87,p88,p89,p90,p91,p92,p93,p94,p95,p96,p97,p98,p99,p100,p101,p102,p103,p104,p105,p106,p107,p108,p109,p110,p111,p112,p113,p114,p115,p116,p117,p118,p119,p120,p121,p122,p123,p124,p125,p126,p127,p128,N,...) N
#define NONIUS_BENCHMARK_CAT__(X1, X2) X1 ## X2
#define NONIUS_BENCHMARK_CAT_(X1, X2) NONIUS_BENCHMARK_CAT__(X1, X2)

#define NONIUS_BENCHMARK(...) NONIUS_BENCHMARK_CAT_(NONIUS_BENCHMARK_,NONIUS_BENCHMARK_CHOOSE_(__VA_ARGS__,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,OLD_,NEW_,ERR_))(__VA_ARGS__)

#endif // NONIUS_BENCHMARK_HPP