Привет, друзья!
Мне полюбилось измерять скорость дорогих операций и выводить их в QDebug. При таком подходе не нужно прибегать к помощи профайлера и можно достаточно быстро получить приблизительный результат оценки производительности.
В связи с этим появилась необходимость в создании класса, который будет запускать таймер в конструкторе и писать в QDebug информацию о времени своей жизни в деструкторе.
Также мне необходимо было, чтобы класс писал информационные сообщения в начале и конце жизни, о том, какую операцию он замерял и была возможность выводить через него другие отладочные сообщения. Важно ещё было учесть вложенность замеряемых функций, то есть, чтобы замерщик внутри замеряемой функции делал отступы при выводе в QDebug.
Ниже приведён код, который мне удалось реализовать. Спасибо Пантеру за помощь.
PerformanceLogger.h
C++ (Qt)
#pragma once
#define PERFORMANCE_LOGGER(message)\
PerformanceLogger performanceLogger(message);\
Q_UNUSED(performanceLogger);
#include <QElapsedTimer>
#include <QString>
#include <QVariant>
class PerformanceLogger
{
Q_DISABLE_COPY(PerformanceLogger)
public:
explicit PerformanceLogger(const QString &message);
~PerformanceLogger();
QString message() const;
void setMessage(const QString &message);
static QString spacer();
static void setSpacer(const QString &spacer);
static size_t instanceCount();
static QString prefix();
static void setPrefix(const QString &prefix);
PerformanceLogger &operator << (const QString &logMessage);
QString spaceWithPrefix() const;
private:
QElapsedTimer timer_;
QString message_;
static size_t instanceCount_;
static QString spacer_;
static QString prefix_;
};
template<class T>
PerformanceLogger &operator << (PerformanceLogger &logger, const T &logMessage){
return logger << QVariant(logMessage).toString();
}
PerformanceLogger.cpp
C++ (Qt)
#include "PerformanceLogger.h"
#include <QtDebug>
size_t PerformanceLogger::instanceCount_ = 0;
QString PerformanceLogger::spacer_ = QStringLiteral(" ");
QString PerformanceLogger::prefix_ = QString();
PerformanceLogger::PerformanceLogger(const QString &message)
: timer_{}
, message_{message}
{
++instanceCount_;
qDebug()<< qUtf8Printable(spaceWithPrefix() + message + "...");
timer_.start();
}
PerformanceLogger::~PerformanceLogger()
{
qDebug() << qUtf8Printable(spaceWithPrefix() + message_) << "done in" << timer_.elapsed() << "ms";
--instanceCount_;
}
QString PerformanceLogger::message() const
{
return message_;
}
void PerformanceLogger::setMessage(const QString &message)
{
message_ = message;
}
QString PerformanceLogger::spacer()
{
return spacer_;
}
void PerformanceLogger::setSpacer(const QString &spacer)
{
spacer_ = spacer;
}
size_t PerformanceLogger::instanceCount()
{
return instanceCount_;
}
QString PerformanceLogger::spaceWithPrefix() const
{
QString result;
for (size_t i = 0; i < instanceCount_ - 1; ++i){
result += spacer_;
}
return result + prefix_;
}
QString PerformanceLogger::prefix()
{
return prefix_;
}
void PerformanceLogger::setPrefix(const QString &prefix)
{
prefix_ = prefix;
}
PerformanceLogger &PerformanceLogger::operator <<(const QString &logMessage)
{
qDebug() << qUtf8Printable(spaceWithPrefix() + logMessage);
return *this;
}
Пример использования
C++ (Qt)
#include "PerformanceLogger.h"
void setupLogger(){
PerformanceLogger::setSpacer("==");
PerformanceLogger::setPrefix(">");
}
void subSubLongOperation(){
PerformanceLogger performanceLogger("Calculating subSubLongOperation");
performanceLogger << "Message inside subSubLongOperation";
QElapsedTimer timer;
timer.start();
while(timer.elapsed() < 1000);
}
void subLongOperation(){
PERFORMANCE_LOGGER("Calculating subLongOperation");
subSubLongOperation();
QElapsedTimer timer;
timer.start();
while(timer.elapsed() < 1000);
}
void longOperation(){
PERFORMANCE_LOGGER("Calculating LongOperation");
subLongOperation();
QElapsedTimer timer;
timer.start();
while(timer.elapsed() < 1000);
}
int main()
{
setupLogger();
PERFORMANCE_LOGGER("Running main function");
longOperation();
return 0;
}
Вывод:
>Running main function...
==>Calculating LongOperation...
====>Calculating subLongOperation...
======>Calculating subSubLongOperation...
======>Message inside subSubLongOperation
======>Calculating subSubLongOperation done in 1000 ms
====>Calculating subLongOperation done in 2000 ms
==>Calculating LongOperation done in 3000 ms
>Running main function done in 3001 ms
Кому нравится - забирайте
. Очень приветствуется конструктивная критика.