Add benchlib

This commit is contained in:
Théophile Bastian 2018-06-04 14:46:55 +02:00
parent f872119189
commit 11a218b6ab
5 changed files with 195 additions and 0 deletions

View file

@ -0,0 +1,103 @@
#include "DwBenchmark.hpp"
#include <ostream>
#include <cassert>
#include <chrono>
#ifdef UNWIND_EH_ELF
#include "../../stack_walker/stack_walker.hpp"
#endif
#ifdef UNWIND_LIBUNWIND
#include <libunwind.h>
#endif
using namespace std;
unique_ptr<DwBenchmark> DwBenchmark::instance = nullptr;
DwBenchmark::DwBenchmark() {
#ifdef UNWIND_EH_ELF
stack_walker_init();
#endif
}
DwBenchmark& DwBenchmark::get_instance() {
if(!DwBenchmark::instance)
instance = unique_ptr<DwBenchmark>(new DwBenchmark);
return *instance;
}
void DwBenchmark::unwind_measure() {
#ifdef UNWIND_EH_ELF
unwind_context_t context = get_context();
SingleUnwind this_measure;
this_measure.nb_frames = 0;
auto start_time = chrono::high_resolution_clock::now();
while(unwind_context(context)) {
this_measure.nb_frames++;
}
auto end_time = chrono::high_resolution_clock::now();
this_measure.nanoseconds = chrono::duration_cast<chrono::nanoseconds>(
end_time - start_time).count();
add_measure(this_measure);
#elif UNWIND_LIBUNWIND
unw_context_t context;
int rc = unw_getcontext(&context);
if(rc < 0)
assert(false);
unw_cursor_t cursor;
rc = unw_init_local(&cursor, &context);
if(rc < 0)
assert(false);
SingleUnwind this_measure;
this_measure.nb_frames = 0;
auto start_time = chrono::high_resolution_clock::now();
while(unw_step(&cursor) > 0) {
this_measure.nb_frames++;
}
auto end_time = chrono::high_resolution_clock::now();
this_measure.nanoseconds = chrono::duration_cast<chrono::nanoseconds>(
end_time - start_time).count();
add_measure(this_measure);
#else
assert(false);
#endif
}
void DwBenchmark::add_measure(const SingleUnwind& measure) {
measures.push_back(measure);
}
void DwBenchmark::add_measure(int nb_frames, size_t microseconds) {
add_measure(SingleUnwind({nb_frames, microseconds}));
}
void DwBenchmark::format_output(std::ostream& os) const {
size_t nb_unwind_frames = 0;
size_t total_nanoseconds = 0;
for(const auto& measure: measures) {
nb_unwind_frames += measure.nb_frames;
total_nanoseconds += measure.nanoseconds;
}
double clock_precision_ns =
((double)
(1000*1000*1000 * std::chrono::high_resolution_clock::period::num))
/ ((double) std::chrono::high_resolution_clock::period::den);
os << "Total time: " << total_nanoseconds << "ns" << endl
<< "Total frames: " << nb_unwind_frames << endl
<< "Avg frames/unwind: "
<< (double)nb_unwind_frames / (double)measures.size() << endl
<< "Avg time/frame: "
<< (double)total_nanoseconds / nb_unwind_frames << "ns" << endl
<< "Clock precision: " << clock_precision_ns << "ns" << endl;
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <memory>
#include <vector>
class DwBenchmark {
/** Singleton class - keeps track of benchmarks performed during a run */
public:
struct SingleUnwind {
int nb_frames;
size_t nanoseconds;
};
static DwBenchmark& get_instance();
void unwind_measure(); ///< Unwind from here, and add the measure
void add_measure(const SingleUnwind& measure); ///< Add this measure
void add_measure(int nb_frames, size_t microseconds);
/** Dump formatted output on `os` displaying stats about this benchmark
* run */
void format_output(std::ostream& os) const;
private:
DwBenchmark();
static std::unique_ptr<DwBenchmark> instance;
std::vector<SingleUnwind> measures;
};

View file

@ -0,0 +1,32 @@
TARGETS=libbench.eh_elf.so libbench.unwind.so
COMMON_OBJS=bench.o
EH_ELF_OBJS=DwBenchmark.eh_elf.o
UNWIND_OBJS=DwBenchmark.unwind.o
CXX=g++
CXXFLAGS=-Wall -Wextra -O2 -std=c++14
CXXLIBS=
all: $(TARGETS)
libbench.eh_elf.so: $(EH_ELF_OBJS) $(COMMON_OBJS)
$(CXX) $(CXXFLAGS) -shared -o $@ $^ $(CXXLIBS) \
-L../../stack_walker -lstack_walker.global
libbench.unwind.so: $(UNWIND_OBJS) $(COMMON_OBJS)
$(CXX) $(CXXFLAGS) -shared -o $@ $^ $(CXXLIBS) \
-lunwind -lunwind-x86_64
%.eh_elf.o: %.cpp
$(CXX) $(CXXFLAGS) -fPIC -DUNWIND_EH_ELF -o $@ -c $<
%.unwind.o: %.cpp
$(CXX) $(CXXFLAGS) -fPIC -DUNWIND_LIBUNWIND -o $@ -c $<
%.o: %.cpp
$(CXX) $(CXXFLAGS) -fPIC -o $@ -c $<
.PHONY: clean
clean:
rm *.o $(TARGETS)

View file

@ -0,0 +1,12 @@
#include "bench.h"
#include <iostream>
#include "DwBenchmark.hpp"
void bench_unwinding() {
DwBenchmark::get_instance().unwind_measure();
}
void bench_dump_data() {
DwBenchmark::get_instance().format_output(std::cout);
}

16
benching/benchlib/bench.h Normal file
View file

@ -0,0 +1,16 @@
/** Benchmarking library: a collection of functions that can be called to
* benchmark dwarf-assembly
**/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void bench_unwinding();
void bench_dump_data();
#ifdef __cplusplus
} // END extern "C"
#endif