Open schwehr opened 7 years ago
e.g.
// https://trac.osgeo.org/gdal/ticket/6790
//
//
// double_is_a_type_test --benchmarks=all
//
// Result:
//
// The unsafe macro and the CPLIsDoubleAnInt2 with the cast tied for
// optimized mode speed.
#include <cmath>
#include <limits>
#include "benchmark.h"
#include "gunit.h"
namespace {
#define CPL_IS_DOUBLE_AN_INT_UNSAFE(d) ((double)(int)(d) == (d))
#define CPL_IS_DOUBLE_AN_INT(d) \
((d) >= INT_MIN && (d) <= INT_MAX && (double)(int)(d) == (d))
inline bool CPLIsDoubleAnInt0(double d) {
return CPL_IS_DOUBLE_AN_INT_UNSAFE(d);
}
inline bool CPLIsDoubleAnInt1(double d) { return CPL_IS_DOUBLE_AN_INT(d); }
// Using "const double &d" was actually slower with -c dbg.
inline bool CPLIsDoubleAnInt2(double d) {
if (d > std::numeric_limits<int>::max()) return false;
if (d < std::numeric_limits<int>::min()) return false;
return d == static_cast<double>(static_cast<int>(d));
}
inline bool CPLIsDoubleAnInt3(double d) {
if (d > std::numeric_limits<int>::max()) return false;
if (d < std::numeric_limits<int>::min()) return false;
double dfTmp = 0.0;
return modf(d, &dfTmp) == 0.0;
}
inline bool CPLIsDoubleAnInt4(const double& d) {
if (d > std::numeric_limits<int>::max()) return false;
if (d < std::numeric_limits<int>::min()) return false;
double dfTmp = 0.0;
return modf(d, &dfTmp) == 0.0;
}
const auto kValuesYes = {-1.0, 0.0, 1.0, -1000001.0, 1000001.0};
const auto kValuesNo = {-1.1, 1e-19, 1.00001, -1000001.999, 1000001.999,
1e100, -1e100, 1.234e300, -1.234e300};
static void BM_MacroUnsafe(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPL_IS_DOUBLE_AN_INT_UNSAFE(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPL_IS_DOUBLE_AN_INT_UNSAFE(v)) << v;
}
}
}
//BENCHMARK(BM_MacroUnsafe);
static void BM_Macro(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPL_IS_DOUBLE_AN_INT(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPL_IS_DOUBLE_AN_INT(v)) << v;
}
}
}
// BENCHMARK(BM_Macro);
static void BM_MacroUnsafeInline(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPLIsDoubleAnInt0(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPLIsDoubleAnInt0(v)) << v;
}
}
}
// BENCHMARK(BM_MacroUnsafeInline);
static void BM_MacroInline(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPLIsDoubleAnInt1(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPLIsDoubleAnInt1(v)) << v;
}
}
}
// BENCHMARK(BM_MacroInline);
static void BM_Cast(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPLIsDoubleAnInt2(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPLIsDoubleAnInt2(v)) << v;
}
}
}
BENCHMARK(BM_MacroUnsafe);
BENCHMARK(BM_Cast);
static void BM_Modf(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPLIsDoubleAnInt3(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPLIsDoubleAnInt3(v)) << v;
}
}
}
// BENCHMARK(BM_Modf);
static void BM_ModfConstRef(benchmark::State& state) {
while (state.KeepRunning()) {
for (const auto& v : kValuesYes) {
CHECK(CPLIsDoubleAnInt4(v)) << v;
}
for (const auto& v : kValuesNo) {
CHECK(!CPLIsDoubleAnInt0(v)) << v;
}
}
}
// BENCHMARK(BM_ModfConstRef);
} // namespace
int main(int argc, char** argv) {
FLAGS_logtostderr = true;
RunSpecifiedBenchmarks();
}
https://github.com/google/benchmark