Skip to content

Instantly share code, notes, and snippets.

@jubnzv
Created January 5, 2021 11:40
Show Gist options
  • Save jubnzv/e355e8c556a4e64c45b86778a8cf6002 to your computer and use it in GitHub Desktop.
Save jubnzv/e355e8c556a4e64c45b86778a8cf6002 to your computer and use it in GitHub Desktop.
#ifndef UBENCH_HPP
#define UBENCH_HPP
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <ostream>
#include <time.h>
#include <unistd.h>
#include <vector>
namespace ubench
{
namespace impl
{
using Time = timespec;
#define CompilerMemBar() std::atomic_signal_fence(std::memory_order_seq_cst)
inline Time get_sys_time()
{
timespec t;
CompilerMemBar();
if (clock_gettime(CLOCK_MONOTONIC_RAW, &t) != 0) {
t.tv_sec = (time_t)-1;
t.tv_nsec = -1;
}
CompilerMemBar();
return t;
}
inline double get_time_delta(Time start)
{
timespec t;
CompilerMemBar();
if ((start.tv_sec == (time_t)-1 && start.tv_nsec == -1) ||
clock_gettime(CLOCK_MONOTONIC_RAW, &t) == -1)
return -1;
CompilerMemBar();
return static_cast<double>(static_cast<long>(t.tv_sec) -
static_cast<long>(start.tv_sec)) *
1000 +
double(t.tv_nsec - start.tv_nsec) / 1'000'000;
}
} // namespace impl
struct stats_t {
stats_t(const std::vector<double> &results)
{
std::copy(results.begin(), results.end(), results_.begin());
std::sort(results.begin(), results.end());
auto test_runs = results.size();
min_ = results[0];
max_ = results[test_runs - 1];
if (test_runs == 1) {
avg_ = results[0];
return;
}
double sum = 0;
double c = 0;
for (std::size_t i = 0; i < test_runs; ++i) {
auto y = results[i] - c;
auto t = sum + y;
c = (t - sum) - y;
sum = t;
}
avg_ = sum / test_runs;
}
void to_csv(std::ostream &os, bool header = true)
{
if (header)
os << "Bench,Time\n";
for (std::size_t i = 0; i < results_.size(); ++i)
os << i << "," << results_[i] << "\n";
}
inline std::vector<double> results() const { return results_; }
inline double min() const { return min_; }
inline double max() const { return max_; }
inline double avg() const { return avg_; }
private:
std::vector<double> results_;
double min_;
double max_;
double avg_;
};
template <typename TFunc>
stats_t ubench_stats(TFunc &&func, std::size_t test_runs = 1)
{
using namespace impl;
auto results = std::vector<double>(test_runs);
for (std::size_t i = 0; i < test_runs; ++i) {
auto start = get_sys_time();
func();
results[i] = get_time_delta(start);
}
return stats_t(results);
}
} // namespace ubench
#endif // UBENCH_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment