Created
January 5, 2021 11:40
-
-
Save jubnzv/e355e8c556a4e64c45b86778a8cf6002 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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