#Глава 38. Boost.Timer Boost.Timer предоставляет часы для измерения производительности кода. В начале, может показаться, что эта библиотека конкурирует с Boost.Chrono. Однако, в то время как Boost.Chrono обеспечивает часы для измерения периодов, Boost.Timer измеряет время, необходимое для исполнения кода. Хотя Boost.Timer использует Boost.Chrono, когда вы хотите измерить производительность кода, вы должны использовать Boost.Timer, вместо Boost.Chrono.
Начиная с версии 1.48.0, библиотек Boost, существует 2 версии Boost.Timer. Первая версия Boost.Timer имеет только один заголовочный файл: boost/timer/timer.hpp
. Не используйте этот заголовочный файл. Он принадлежит к первой версии Boost.Timer, которая больше не использвутеся.
Часы, предоставляемые Boost.Timer реализуются в классах boost::timer::cpu_timer
и boost::timer::auto_cpu_timer
. boost::timer::auto_cpu_timer
происходит от boost::timer::cpu_timer
и автоматически останавливает время в деструкторе. Затем он записывает время в выходной поток.
Пример 38.1 начинается с представления класса boost::timer::cpu_timer
. Этот пример и следующие, делают некоторые расчеты, чтобы убедиться, что проходит достаточно времени для его измерения. В противном случае таймеры будут всегда равны 0 и будет трудно использовать часы из этой библиотеки.
Пример 38.1. Измерение времени с boost::timer::cpu_timer
#include <boost/timer/timer.hpp>
#include <iostream>
#include <cmath>
using namespace boost::timer;
int main()
{
cpu_timer timer;
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
std::cout << timer.format() << '\n';
}
Измерение начинается, когда boost::timer::cpu_timer
инстанцирован. Вы можете вызвать член-функцию format()
в любой момент, чтобы получить истекшее время. Пример 38.1 показывает выход в следующем формате: 0.099170s wall, 0.093601s user + 0.000000s system = 0.093601s CPU (94.4%).
Boost.Timer измеряет фактическое время и время центрального процессора. Фактическое время - это время, которое проходит в соответствии с текущим временем. Вы могли бы измерить это время секундомером. Процессорное временя говорит, сколько времени затратила программа, на выполнение кода. На современных многозадачных системах процессор не доступен для программы все время. Программа также может остановится и ждать ввода пользователя. В этих случаях время задержки движется дальше, но не время центрального процессора.
Процессорное время делится между временем потраченным в режиме пользователя и в режиме ядра. Режим ядра относится к коду, который является частью операционной системы. Режим пользователя - код, который не относится к операционной системе. Режим пользователя включает пользовательский код и код от сторонних библиотек. Например, библиотека Boost, включает режим пользователя. Количество времени, затраченного в режиме ядра зависит от операционной системы, вызываемых функций и времени на их исполнение.
Пример 38.2. Остановка и возобновление таймеров
#include <boost/timer/timer.hpp>
#include <iostream>
#include <cmath>
using namespace boost::timer;
int main()
{
cpu_timer timer;
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
std::cout << timer.format() << '\n';
timer.stop();
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
std::cout << timer.format() << '\n';
timer.resume();
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
std::cout << timer.format() << '\n';
}
boost::timer::cpu_timer
предоставляет функции-члены stop()
и resume()
, которые остановливают и возобновляют таймер. В примере 38.2 таймер останавливается перед вторым циклом for
и возобновляется после него. Таким образом, второй цикл for
не измеряется. Это похоже на секундомер, который останавливают, а затем возобновляют через некоторое время. Время, которое возвращается после второго вызова format()
в примере 38.2, такое же, если бы второй цикл for
не существовал.
boost::timer::cpu_timer
также предоставляет функцию-член start()
. Если вы вызываете start()
, вместо resume()
, таймер обнуляется. Конструктор boost::timer::cpu_timer
вызывает start()
, поэтому таймер запускается сразу, как инстанцируется boost::timer::cpu_timer
.
**Пример 38.3. Получение фактического времени и времени центрального процессора, как кортеж **
#include <boost/timer/timer.hpp>
#include <iostream>
#include <cmath>
using namespace boost::timer;
int main()
{
cpu_timer timer;
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
cpu_times times = timer.elapsed();
std::cout << times.wall << '\n';
std::cout << times.user << '\n';
std::cout << times.system << '\n';
}
Пока format()
возвращает измеренные фактическое время и процессорное время в виде строки, так же можно получить время в кортеже смотри пример 38.3. boost::timer::cpu_timer
предоставляет член-функцию elapsed()
для этого. elapsed()
возвращает кортеж типа boost::timer::times
. Этот кортеж имеет три переменных: wall, user, и system. Эта переменная содержит фактическое время и время центрального процессора в наносекундах. Их тип boost::int_least64_t
.
boost::timer::times
предоставляет член-функцию clear()
, чтобы обнулить wall, user и system.
Пример 38.4. Измерение времени автоматически с помощью boost::timer::auto_cpu_timer
#include <boost/timer/timer.hpp>
#include <cmath>
using namespace boost::timer;
int main()
{
auto_cpu_timer timer;
for (int i = 0; i < 1000000; ++i)
std::pow(1.234, i);
}
Вы можете измерить задержку и процессорное время блока кода с boost::timer::auto_cpu_timer
. Поскольку деструктор этого класса останавливает время измерения и записывает время в стандартный поток вывода, пример 38.4 делает то же самое, что и Пример 38.1.
boost::timer::auto_cpu_timer
предоставляет несколько конструкторов. Например, вы можете передать выходной поток, который будет использоваться для отображения времени. По умолчанию выходной поток std::cout
.
Вы можете указать формат времени для boost::timer::auto_cpu_timer
и boost::timer::cpu_timer
. Boost.Timer обеспечивает флаги формата, похожие на, флаги формата, поддерживаемого Boost.Format или std::printf()
. Документация содержит обзор флагов формата.