C++ Замер производительности
От: VNG Беларусь https://organicmaps.app/
Дата: 28.01.06 18:10
Оценка: 6 (1)
Написаны макросы для замера производительности отдельных участков кода и вывода результатов в файл. Используется функция QueryPerformanceCounter.
Выводится:
— общее время выполнения участка кода
— количество раз, которое выполнялся участок кода
— среднее время работы участка кода

Пример использования:
DECLARE_PERFORMANCE_FILE_STREAM(F:\\finish_dos_point_perf.log, perfFile);

DECLARE_PERFORMANCE_CHECKER(1, perfFile);
START_PERFORMANCE_CHECK(1);
// участок номер 1 для замера
FINISH_PERFORMANCE_CHECK(1);

DECLARE_PERFORMANCE_CHECKER(2, perfFile);
START_PERFORMANCE_CHECK(2);
// участок номер 2 для замера
FINISH_PERFORMANCE_CHECK(2);


Собственно, сама реализация.
#pragma once

#include <fstream>
#include <string>

namespace performance 
{
    /// Класс замера времени.
    class timer
    {
        LARGE_INTEGER m_start;

    public:

        inline void start() { QueryPerformanceCounter(&m_start); }

        inline double finish()
        {
            LARGE_INTEGER finish;
            QueryPerformanceCounter(&finish);
            LARGE_INTEGER freq;
            QueryPerformanceFrequency(&freq);
            return double(finish.QuadPart - m_start.QuadPart) / double(freq.QuadPart);
        }

        template <class TStream> void finish_output(TStream & out)
        {
            out << finish() << std::endl;
        }
    };

    /// Класс замера производительности многократного выполнения некого куска кода.
    /// Накапливает статистику по времени ее выполнения и количества выполнения.
    class instruction_checker
    {
        timer m_timer;

        class instruction_info
        {
            double m_time;
            size_t m_count;

        public:

            instruction_info() : m_time(0.0), m_count(0) {}
            void add_time(double time) { m_time += time; }
            void inc_count() { ++m_count; }

            inline double get_time() const { return m_time; }
            inline size_t get_count() const { return m_count; }
            inline double get_average_time() const { return m_time / double(m_count); }
        } m_info;

    public:

        inline void start() { m_timer.start(); }
        inline void finish()
        {
            m_info.add_time(m_timer.finish());
            m_info.inc_count();
        }

        inline double get_time() const { return m_info.get_time(); }
        inline size_t get_count() const { return m_info.get_count(); }
        inline double get_average_time() const { return m_info.get_average_time(); }
    };

    /// Класс - guard для замера многократно-вызываемого участка кода.
    /// Имеет интерфейс класса performance_instruction_checker и дополнительно
    /// в деструкторе выводит в поток накопленную информацию.
    /// Должен использоваться как статический экземпляр в функции.
    class stream_guard
    {
        instruction_checker m_checker;
        int m_instructionNumber;
        std::ofstream & m_outFile;
    public:
        stream_guard(int instructionNumber, std::ofstream & outFile)
            : m_instructionNumber(instructionNumber), m_outFile(outFile)
        {
        }
        inline void start() { m_checker.start(); }
        inline void finish() { m_checker.finish(); }
        ~stream_guard()
        {
            m_outFile << "Instruction number = " << m_instructionNumber << std::endl;
            m_outFile << "Hole time = " << m_checker.get_time() << std::endl;
            m_outFile << "Call count = " << static_cast<unsigned int>(m_checker.get_count()) << std::endl;
            m_outFile << "Average time = " << m_checker.get_average_time() << std::endl;
            m_outFile << "===============================================" << std::endl;
        }
    };
}

/// Макрос задания файла для накопления статистики
#define DECLARE_PERFORMANCE_FILE_STREAM(fileName, varName)    \
    static std::ofstream varName(#fileName)

/// Макрос задания статического экземпляра checkera
#define DECLARE_PERFORMANCE_CHECKER(index, outFile)    \
    static performance::stream_guard performance_checker_##index(index, outFile)

/// Макрос начала замера
#define START_PERFORMANCE_CHECK(index)    \
    performance_checker_##index.start()

/// Макрос конца замера
#define FINISH_PERFORMANCE_CHECK(index)    \
    performance_checker_##index.finish()
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: C++ Замер производительности
От: MShura  
Дата: 28.01.06 20:38
Оценка:
А зачем использовать плавающую точку в целочисленной задаче?
Re: C++ Замер производительности
От: ilnar Россия  
Дата: 30.01.06 06:27
Оценка:
Здравствуйте, VNG, Вы писали:

VNG>Написаны макросы для замера производительности отдельных участков кода и вывода результатов в файл. Используется функция QueryPerformanceCounter.


тоже этими функциями пользовался пока не понадобилось знать точно скока именной мой процесс/поток пожирает. начал пользоваться другими, точность такого же высокого уровня, правда седует уточнить
Get{Process|Thread}Times
Re[2]: C++ Замер производительности
От: VNG Беларусь https://organicmaps.app/
Дата: 30.01.06 14:10
Оценка:
Здравствуйте, MShura, Вы писали:

MS>А зачем использовать плавающую точку в целочисленной задаче?


Ну здесь я рассуждал просто. Чтобы не потерять значимое время в случае, когда кусок кода выполняется очень много раз.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: C++ Замер производительности
От: korzhik Россия  
Дата: 30.01.06 14:14
Оценка:
Здравствуйте, VNG, Вы писали:

VNG>Написаны макросы для замера производительности отдельных участков кода и вывода результатов в файл. Используется функция QueryPerformanceCounter.

VNG>Выводится:
VNG>- общее время выполнения участка кода
VNG>- количество раз, которое выполнялся участок кода
VNG>- среднее время работы участка кода

[]

Я б добавил бы сюда:
    HANDLE hProcess = GetCurrentProcess();
   SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);

   // run tests

   // set priority back normal
   SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS);


хотя, конечно же, юзер может это сделать сам если захочет.
Re[2]: C++ Замер производительности
От: ilnar Россия  
Дата: 30.01.06 14:17
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, VNG, Вы писали:


VNG>>Написаны макросы для замера производительности отдельных участков кода и вывода результатов в файл. Используется функция QueryPerformanceCounter.

VNG>>Выводится:
VNG>>- общее время выполнения участка кода
VNG>>- количество раз, которое выполнялся участок кода
VNG>>- среднее время работы участка кода

K>[]


K>Я б добавил бы сюда:

K>
K>    HANDLE hProcess = GetCurrentProcess();
K>   SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);

K>   // run tests

K>   // set priority back normal
K>   SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS);
K>


K>хотя, конечно же, юзер может это сделать сам если захочет.


вот как раз для избежания этих неточностей желательно использование GetProcessTimes и GetThreadTimes
иначе точность малая при телодвижениях других процессов
Re[3]: C++ Замер производительности
От: MShura  
Дата: 30.01.06 15:02
Оценка:
MS>>А зачем использовать плавающую точку в целочисленной задаче?

VNG>Ну здесь я рассуждал просто. Чтобы не потерять значимое время в случае, когда кусок кода выполняется очень много раз.


Получилось как раз наоборот:
— От Windows ты получаешь 64 битовое число, которое в общем случае нельзя представить 64 битовым double.
— При суммировании чисел типа double происходит накопление ошибки. Ошибка тем более значимая, чем чаще выполняется код.

При суммировании целочисленных типов (например INT64) ошибки накопления исключены.
Re: C++ Замер производительности
От: Tanker  
Дата: 01.03.06 13:33
Оценка:
БАЯН

Время жизни этого формума можно мерить по очередным "изобретениям" QueryPerformanceCounter
The animals went in two by two, hurrah, hurrah...
Re[2]: C++ Замер производительности
От: VNG Беларусь https://organicmaps.app/
Дата: 01.03.06 14:11
Оценка:
Здравствуйте, Tanker, Вы писали:

T>БАЯН


Ну так можно сказать, что любая программа или библиотека есть ничто иное как набор велосипедов с различной формой колес, собраннх вместе, обработаных напильником и скомпонованных вместе.

T>Время жизни этого формума можно мерить по очередным "изобретениям" QueryPerformanceCounter


QueryPerformanceCounter я не изобретал. Внимательно читаем шапку первоначального поста.
... << RSDN@Home 1.1.4 stable rev. 510>>
Re: C++ Замер производительности
От: Left2 Украина  
Дата: 01.03.06 14:32
Оценка:
Пользоваться твоими макросами неудобно. Я бы предпочёл иметь класс, в котором конструктор принимает номер (имя было бы предпочтительнее) участка и сразу же начинает измерение, а в деструкторе его заканчивает. Ну и конечно же неплохо было бы иметь возможность останавливать-запускать измерение времени конкретным экземпляром класса. По крайней мере, в своём велосипеде я так делал
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: C++ Замер производительности
От: VNG Беларусь https://organicmaps.app/
Дата: 01.03.06 15:00
Оценка:
Здравствуйте, Left2, Вы писали:

L>Пользоваться твоими макросами неудобно.


Так я и не особо претендовал. Просто изложил идею. Для моей локальной задачи нахождения боттл-нек в нескольких функциях это было оптимальное решение.

L> Я бы предпочёл иметь класс, в котором конструктор принимает номер (имя было бы предпочтительнее) участка и сразу же начинает измерение, а в деструкторе его заканчивает. Ну и конечно же неплохо было бы иметь возможность останавливать-запускать измерение времени конкретным экземпляром класса. По крайней мере, в своём велосипеде я так делал


Можно и такой огород городить:

class perf_singleton
{
 std::map<std::string, perf_info> m_info;
public:
 static perg_singleton & instance();
 void update(std::string const & blockName, _int64 time);
 voit put_to_stream(std::ostream & stream);
};

class perf_counter
{
public:
 perf_conter(std::string const & blockName);
 ~perf_counter()
 {
  perf_singleton::instance().update(m_blockName, m_time);
 }
};

int main()
{
 {
  perf_counter counter("block1");
    // some portion of code
 }
 
 {
  perf_counter counter("block2");
    // another portion of code
 }
 
 perf_singleton::instance().put_to_stream(std::cout);
}
... << RSDN@Home 1.1.4 stable rev. 510>>
Re[2]: C++ Замер производительности
От: McSeem2 США http://www.antigrain.com
Дата: 02.03.06 05:17
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Я б добавил бы сюда:

K>    HANDLE hProcess = GetCurrentProcess();
K>   SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);


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