Add benchlib
This commit is contained in:
parent
f872119189
commit
11a218b6ab
103
benching/benchlib/DwBenchmark.cpp
Normal file
103
benching/benchlib/DwBenchmark.cpp
Normal 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;
|
||||
}
|
32
benching/benchlib/DwBenchmark.hpp
Normal file
32
benching/benchlib/DwBenchmark.hpp
Normal 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;
|
||||
};
|
32
benching/benchlib/Makefile
Normal file
32
benching/benchlib/Makefile
Normal 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)
|
12
benching/benchlib/bench.cpp
Normal file
12
benching/benchlib/bench.cpp
Normal 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
16
benching/benchlib/bench.h
Normal 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
|
Loading…
Reference in a new issue