Skip to content

Commit

Permalink
Introduce Benchmark*
Browse files Browse the repository at this point in the history
  • Loading branch information
Al2Klimov committed Dec 10, 2024
1 parent e50eb52 commit e1bee78
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(base_SOURCES
atomic.hpp
atomic-file.cpp atomic-file.hpp
base64.cpp base64.hpp
benchmark.cpp benchmark.hpp
boolean.cpp boolean.hpp boolean-script.cpp
bulker.hpp
configobject.cpp configobject.hpp configobject-ti.hpp configobject-script.cpp
Expand Down
20 changes: 20 additions & 0 deletions lib/base/benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */

#include "base/benchmark.hpp"

using namespace icinga;

/**
* Adds the time elapsed since watch.GetStartTime() to this instance.
*
* May be called multiple times to accumulate time.
*
* @param watch The watch to get the start time from
*
* @return This instance for method chaining
*/
BenchmarkSummary& BenchmarkSummary::operator+=(const BenchmarkStopWatch& watch) noexcept
{
m_Sum.fetch_add((BenchmarkStopWatch::Clock::now() - watch.GetStartTime()).count(), std::memory_order_relaxed);
return *this;
}
65 changes: 65 additions & 0 deletions lib/base/benchmark.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */

#pragma once

#include "base/atomic.hpp"
#include <chrono>

namespace icinga
{

/**
* Stopwatch for benchmarking.
*
* @ingroup base
*/
class BenchmarkStopWatch {
public:
using Clock = std::chrono::steady_clock;

/**
* Captures the current time for later subtraction.
*
* May be called multiple times to re-start the timer.
*/
void Start() noexcept
{
m_Start = Clock::now();
}

/**
* @return The last time Start() was called
*/
[[nodiscard]] Clock::time_point GetStartTime() const noexcept
{
return m_Start;
}

private:
Clock::time_point m_Start;
};

/**
* Benchmark result.
*
* @ingroup base
*/
class BenchmarkSummary
{
public:
BenchmarkSummary& operator+=(const BenchmarkStopWatch&) noexcept;

/**
* @return The total accumulated time in seconds
*/
template<class T>
explicit operator T() const noexcept
{
return std::chrono::duration<T>(BenchmarkStopWatch::Clock::duration(m_Sum.load(std::memory_order_relaxed))).count();
}

private:
Atomic<BenchmarkStopWatch::Clock::duration::rep> m_Sum {0};
};

}
3 changes: 3 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ set(base_test_SOURCES
icingaapplication-fixture.cpp
base-array.cpp
base-base64.cpp
base-benchmark.cpp
base-convert.cpp
base-dictionary.cpp
base-fifo.cpp
Expand Down Expand Up @@ -112,6 +113,8 @@ add_boost_test(base
base_array/clone
base_array/json
base_base64/base64
base_benchmark/one_second
base_benchmark/two_seconds
base_convert/tolong
base_convert/todouble
base_convert/tostring
Expand Down
45 changes: 45 additions & 0 deletions test/base-benchmark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* Icinga 2 | (c) 2024 Icinga GmbH | GPLv2+ */

#include "base/benchmark.hpp"
#include "base/utility.hpp"
#include <BoostTestTargetConfig.h>
#include <cmath>

using namespace icinga;

static bool AssertSumSeconds(BenchmarkSummary& sum, long double seconds)
{
return std::abs(((long double)sum - seconds) / seconds) < 0.05;
}

BOOST_AUTO_TEST_SUITE(base_benchmark)

BOOST_AUTO_TEST_CASE(one_second)
{
BenchmarkSummary sum;
BenchmarkStopWatch sw;

sw.Start();
Utility::Sleep(1);
sum += sw;

BOOST_CHECK(AssertSumSeconds(sum, 1));
}

BOOST_AUTO_TEST_CASE(two_seconds)
{
BenchmarkSummary sum;
BenchmarkStopWatch sw;

sw.Start();
Utility::Sleep(1);
sum += sw;

sw.Start();
Utility::Sleep(1);
sum += sw;

BOOST_CHECK(AssertSumSeconds(sum, 2));
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit e1bee78

Please sign in to comment.