#define Макрос и Шаблон, которые будут запускать функции любого типа, включая void, и возвращать среднее время выполнения? - PullRequest
0 голосов
/ 04 декабря 2018

Backstory

(Вы можете пропустить. Полезно, если вы хотите расширить и принять мой подход.)

Я пытаюсь расширить библиотеку отладки, которую я создал, чтобы иметь возможность проводить ненавязчивый бенчмаркинги отладка.Пока это выглядит примерно так, однако я открыт для реконструкции.Это похоже на то, что я использовал для гибкой отладки типов:

#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};
}

Актуальный вопрос

Возьмите следующий код:

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цель состоит в том, чтобы MyClass::bar() вывел это: (случайные числа составлены для начального и среднего значения)

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

Таким образом, как я могу сделать так, чтобы макрос BENCH() мог принимать любой тип функции,запускать его N раз, сравнивая, сколько времени занимает каждая итерация и возвращает ли оно первое начальное значение, полученное при первом запуске?

Оно не может быть навязчивым, что делает эту строку возможной:

QString s = BENCH(funString(),2000);
...