Backstory
(You can skip. Useful if you want to expand and adopt my approach.)
I am trying to expand a debugging library I created to be able to do unintrusive benchmarking and debugging. So far, it looks something like this, however I am open to revamping. This is just similar to what I was using for doing type flexible debugging:
#define BENCH(FUNC,N)CT::bench(#FUNC,FUNC,N,__FILE__,__LINE__,__PRETTY_FUNCTION__)
// #FUNC is a string of the code for the function placed in the macro
// FUNC is the function. How it should be captured, I am not sure yet.
// N Should be the number of times you wish to run the captured function
// __FILE__, __LINE__, __PRETTY_FUNCTION__ are GCC predefined macros
// Used for easily locating the code that is generating the output.
template <typename First> // Problem: Ensure only functions used as arguments?
static First bench(const QString expression,
First &&type, // This is the type. Needed for the return.
quint64 repeatN, // Negative repeats make no sense.
const QString &_file,
const int &_line,
const QString &_pretty_function)
{
QString typeName = QConsoleToolkit::demangle(typeid(type).name());
int initial(-1); // Time required to execute function first time
int average(-1); // Average execution time.
for (int i=0; i < repeatN; i++) {
// *
// *
// No idea how to do this.
// Please help.
// *
// *
}
QTextStream(stdout)
<< "Benchmark: " << typeName
<< "\t" << expression
<< "\t" << _pretty_function
<< "\t" << _file
<< ":" << _line << endl
<< " Repeat: " << QString::number(repeatN) << endl
<< "Initial: " << QString::number(initial) << endl
<< "Average: " << QString::number(average) << endl;
// Unsure if this will work with void
return std::forward<First>(type);
}
// Returns string for type
QString CT::demangle(const QString &name)
{
int status;
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name.toLatin1(), NULL, NULL, &status),
std::free
};
return {(status==0) ? QLatin1String(res.get()) : name};
}
Actual Question
Take the following code:
void MyClass::foo()
{
//dostuff
}
QString MyClass::funString()
{
return "The quick brown fox jumps over the lazy dog";
}
void MyClass::bar()
{
BENCH(foo(), 1000);
QString s = BENCH(funString(),2000);
QTextStream(stdout) << s << endl;
}
My goal is to have MyClass::bar()
output this: (Random numbers are made up for initial and average)
Benchmark: void foo() void MyClass::bar() /home/akiva/myclass.cpp:31
Repeat: 1000
Initial: 2523
Average: 1234
Benchmark: QString funString() void MyClass::bar() /home/akiva/myclass.cpp:32
Repeat: 2000
Initial: 5003
Average: 4025
The quick brown fox jumps over the lazy dog
Thus, how can I make it so the macro BENCH()
can take any type of function, run it N
times, benchmarking how long each iteration takes to run, and have it return the first initial value received upon initial run?
It can not be intrusive, thus making this line possible:
QString s = BENCH(funString(),2000);