Недавно, я чуть-чуть поменял алгоритм работы программы. И, на глазок, приложение стало работать чуть дольше. Мне захотелось сравнить время работы старой и новой функции. Написав нехитрый код, я замерил время работы и количество вызовов. Но эта функция вызывает десяток других. У меня возник вопрос: "Какую из ни следует оптимизировать". Копи-паст и вот я получил необходимые данные. Чем дольше я разбирался, тем больше меня бесил копи-паст. А потом это все вычищать
Можно, конечно, воспользоваться профиляторм, но:
1. Многие из них стоят денег (под Винду).
2. Надо перекомпилировать весь проект.
3. Много избыточной информации.
4. Сложность использования.
Поэтому я решил написать что-то, чтоб одной строкой вставлять в функцию все необходимое для её анализа.
Порядок работы:
1. Подключаем gaudge.h.
2. В начале функции вставляем макрос MEASUREIT.
CClass::Method()
{
MEASUREIT;
// делаем много-много действий
}
3. Компилируем программу, запускаем, работаем, закрываем.
4. В консоли получаем строку вида
"CClass::Method" Time: 23. Count: 12 .
, где
Time - общее время выполнения функции
Count - количество вызовов.
Ну собственно код.
gaudge.h/*! \file gaudge.h
* \brief Файл со свем необходимым для измерения времени работы функций.
* \author SASA.
* \date 2010/10/14
*/
#ifndef MED_GAUDGE_H
#define MED_GAUDGE_H
#include <QString>
#include <QTime>
/// Напишите этот макрос в самом начале функции, и по концу программы будет выдана статистика: сколько раз вызвали, сколько времени потратили.
#define MEASUREIT static CGaudge gaudge_339b8a83_553b_4adc_955c_718943a1462f(__FUNCTION__); \
CGaudgeHelpper gaudgehelper_9357359e_3a55_40e2_aca8_0be960a81c78(&gaudge_339b8a83_553b_4adc_955c_718943a1462f);
/*! \brief Класс измеритель времени работы метода и количества вызовов.
* \author SASA
* \date 2010/10/14
*/
class CGaudge
{
public:
/*! \brief Создать измеряльщик.
* \param[in] _name (\c const QString) - Имя измерямого объекта.
*/
CGaudge(const QString _name);
~CGaudge(void);
void incrementCount() { m_callCount++; }
void startTimeMeasuring();
void stopTimeMeasuring();
protected:
int m_callTime; ///< Время вызова.
int m_callCount; ///< Количество вызовов.
QString m_name; ///< Имя измерямого объекта.
QTime m_stopwatch; ///< Часики для засечки времени.
};
/*! \brief Класс автоматом начинает и заканчивает измерение.
* \author SASA
* \date 2010/10/14
*/
class CGaudgeHelpper
{
public:
CGaudgeHelpper(CGaudge * _guadge);
~CGaudgeHelpper();
protected:
CGaudge * m_guadge; ///< Измеритель, с которым работаем
};
#endif // MED_GAUDGE_H
gaudge.cpp#include "gaudge.h"
#include <QtCore>
CGaudge::CGaudge( const QString _name )
{
m_callTime = 0;
m_callCount = 0;
m_name = _name;
}
CGaudge::~CGaudge(void)
{
qDebug() << m_name << "Time: " << m_callTime << ". Count: " << m_callCount << ".";
}
void CGaudge::startTimeMeasuring()
{
m_stopwatch.restart();
}
void CGaudge::stopTimeMeasuring()
{
m_callTime += m_stopwatch.elapsed();
}
CGaudgeHelpper::CGaudgeHelpper(CGaudge * _guadge)
{
m_guadge = _guadge;
if(m_guadge)
{
m_guadge->incrementCount();
m_guadge->startTimeMeasuring();
}
}
CGaudgeHelpper::~CGaudgeHelpper()
{
if(m_guadge)
{
m_guadge->stopTimeMeasuring();
}
}
Сразу хочу заметить, что данные о времени не претендуют на точность и нужны для относительной оценки.
И ещё - код не является потоконезависимым. Как понадобится, перепишу для работы для работы с несколькими потоками.