Benchmark
СОДЕРЖАНИЕ
- ИМЯ
- СИНТАКСИС
- ОПИСАНИЕ
- Объект Benchmark
- ЗАМЕЧАНИЯ
- ПРИМЕРЫ
- НАСЛЕДОВАНИЕ
- ОГРАНИЧЕНИЯ
- СМОТРИТЕ ТАКЖЕ
- АВТОРЫ
- ИСТОРИЯ ИЗМЕНЕНИЙ
ИМЯ
Benchmark - измерение времени выполнения кода Perl
СИНТАКСИС
use Benchmark qw(:all) ;
timethis ($count, "code");
# Use Perl code in strings...
timethese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
# ... or use subroutine references.
timethese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# cmpthese can be used both ways as well
cmpthese($count, {
'Name1' => '...code1...',
'Name2' => '...code2...',
});
cmpthese($count, {
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
});
# ...or in two stages
$results = timethese($count,
{
'Name1' => sub { ...code1... },
'Name2' => sub { ...code2... },
},
'none'
);
cmpthese( $results ) ;
$t = timeit($count, '...other code...')
print "$count loops of other code took:",timestr($t),"\n";
$t = countit($time, '...other code...')
$count = $t->iters ;
print "$count loops of other code took:",timestr($t),"\n";
# enable hires wallclock timing if possible
use Benchmark ':hireswallclock'; ОПИСАНИЕ
Модуль Benchmark содержит набор процедур, помогающих определить время выполнения некоторого кода.
timethis - выполнение фрагмента кода несколько раз
timethese - выполнение нескольких фрагментов кода несколько раз
cmpthese - вывод результатов timethese в виде сравнительной таблицы
timeit - выполнение фрагмента кода и измерение времени
countit - подсчёт числа выполнений фрагмента кода за заданное время
Методы
- new
-
Возвращает текущее время. Пример:
use Benchmark; $t0 = Benchmark->new; # ... your code here ... $t1 = Benchmark->new; $td = timediff($t1, $t0); print "the code took:",timestr($td),"\n"; - debug
-
Включает или выключает отладку, устанавливая флаг
$Benchmark::Debug:Benchmark->debug(1); $t = timeit(10, ' 5 ** $Global '); Benchmark->debug(0); - iters
-
Возвращает количество итераций.
Стандартные Экспорты
Следующие процедуры будут экспортированы в ваше пространство имён, если вы используете модуль Benchmark:
- timeit(COUNT, CODE)
-
Аргументы: COUNT - количество раз для выполнения цикла, а CODE - код для выполнения. CODE может быть либо ссылкой на код, либо строкой, которая будет интерпретироваться; в любом случае он будет выполняться в пакете вызывающего модуля.
Возвращает: объект Benchmark.
- timethis ( COUNT, CODE, [ TITLE, [ STYLE ]] )
-
Измеряет время выполнения COUNT итераций CODE. CODE может быть строкой для интерпретации или ссылкой на код; в любом случае CODE будет выполняться в пакете вызывающего модуля. Результаты будут выведены в STDOUT как TITLE, за которым следуют времена. TITLE по умолчанию равен "timethis COUNT", если не указан. STYLE определяет формат вывода, как описано для timestr() ниже.
COUNT может быть нулевым или отрицательным: это означает минимальное количество процессорных секунд для выполнения. Ноль означает значение по умолчанию - 3 секунды. Например, для выполнения как минимум 10 секунд:
timethis(-10, $code)или для выполнения двух тестов кода как минимум 3 секунды:
timethese(0, { test1 => '...', test2 => '...'})Процессорные секунды, в терминах UNIX, представляют собой время пользователя плюс время системы самого процесса, в отличие от реального (по часам) времени и времени, затраченного дочерними процессами. Меньше 0,1 секунды не принимается (-0,01 как счётчик, например, вызовет исключение времени выполнения).
Обратите внимание, что процессорные секунды являются минимальным временем: планирование процессора и другие факторы операционной системы могут усложнить попытку так, что будет затрачено немного больше времени. Однако вывод измерения также укажет количество
$codeзапусков в секунду, что должно быть более интересным числом, чем фактически затраченные секунды.Возвращает объект Benchmark.
- timethese ( COUNT, CODEHASHREF, [ STYLE ] )
-
CODEHASHREF — это ссылка на хэш, содержащий имена в качестве ключей и либо строку для интерпретации, либо ссылку на код для каждого значения. Для каждой пары (KEY, VALUE) в CODEHASHREF эта процедура вызовет
timethis(COUNT, VALUE, KEY, STYLE)Процедуры вызываются в порядке сравнения строк KEY.
COUNT может быть нулевым или отрицательным, см. timethis().
Возвращает ссылку на хэш объектов Benchmark, индексированных по имени.
- timediff ( T1, T2 )
-
Возвращает разность между двумя временами Benchmark как объект Benchmark, подходящий для передачи в timestr().
- timestr ( TIMEDIFF, [ STYLE, [ FORMAT ] ] )
-
Возвращает строку, форматирующую времена в объекте TIMEDIFF в запрошенном стиле. TIMEDIFF ожидается как объект Benchmark, подобный возвращаемому timediff().
STYLE может быть любым из 'all', 'none', 'noc', 'nop' или 'auto'. 'all' показывает каждое из 5 доступных времён ('wallclock', время пользователя, время системы, время пользователя дочерних процессов и время системы дочерних процессов). 'noc' показывает все, кроме двух времён дочерних процессов. 'nop' показывает только время по часам и два времени дочерних процессов. 'auto' (по умолчанию) будет действовать как 'all', если времена дочерних процессов оба равны нулю, в противном случае он действует как 'noc'. 'none' предотвращает вывод.
FORMAT — это спецификатор формата в стиле printf(3) (без ведущего '%'), который необходимо использовать для вывода времён. По умолчанию он равен '5.2f'.
Дополнительные Экспорты
Следующие процедуры будут экспортированы в ваше пространство имён, если вы явно попросите их импортировать:
- clearcache ( COUNT )
-
Очистить кэшированные времена для COUNT раундов нулевого цикла.
- clearallcache ( )
-
Очистить все кэшированные времена.
- cmpthese ( COUNT, CODEHASHREF, [ STYLE ] )
- cmpthese ( RESULTSHASHREF, [ STYLE ] )
-
Вызывает timethese(), затем выводит сравнительную таблицу. Это:
cmpthese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;выводит таблицу типа:
Rate b a b 2831802/s -- -61% a 7208959/s 155% --Эта таблица отсортирована от самого медленного к самому быстрому и показывает процентную разницу в скорости между каждой парой тестов.
cmptheseтакже может принять структуру данных, возвращаемую timethese():$results = timethese( -1, { a => "++\$i", b => "\$i *= 2" } ) ; cmpthese( $results );в случае, если вы хотите увидеть оба набора результатов. Если первый аргумент — не освящённая ссылка на хэш, это RESULTSHASHREF; в противном случае это COUNT.
Возвращает ссылку на МАССИВ строк, каждая строка — МАССИВ ячеек из вышеуказанной таблицы, включая метки. Это:
my $rows = cmpthese( -1, { a => '++$i', b => '$i *= 2' }, "none" );возвращает структуру данных типа:
[ [ '', 'Rate', 'b', 'a' ], [ 'b', '2885232/s', '--', '-59%' ], [ 'a', '7099126/s', '146%', '--' ], ]ПРИМЕЧАНИЕ: Это значение результата отличается от предыдущих версий, которые возвращали
timethese()структуру результата. Если вам нужна эта структура, просто используйте приведенный выше идиом с двумя утверждениямиtimethese...cmpthese.Кстати, обратите внимание на различия в значениях результатов между двумя примерами; это типично для измерений. Если это было бы реальное измерение, вы, вероятно, хотели бы запустить гораздо больше итераций.
- countit(TIME, CODE)
-
Аргументы: TIME — минимальная продолжительность выполнения CODE, а CODE — код для выполнения. CODE может быть либо ссылкой на код, либо строкой для интерпретации; в любом случае он будет выполняться в пакете вызывающего модуля.
TIME не отрицательный. countit() выполнит цикл много раз, чтобы рассчитать скорость CODE перед выполнением его в течение TIME. Фактическое время выполнения обычно будет больше TIME из-за разрешения системных часов, поэтому лучше смотреть на количество итераций, делённых на интересующие вас временные интервалы, а не только на итерации.
Возвращает: объект Benchmark.
- disablecache ( )
-
Отключить кэширование измерений для нулевого цикла. Это заставит Benchmark пересчитывать эти измерения для каждого нового фрагмента кода.
- enablecache ( )
-
Включить кэширование измерений для нулевого цикла. Время, затраченное на COUNT раундов нулевого цикла, будет вычисляться только один раз для каждого используемого COUNT.
- timesum ( T1, T2 )
-
Возвращает сумму двух времён Benchmark как объект Benchmark, подходящий для передачи в timestr().
:hireswallclock
Если модуль Time::HiRes был установлен, вы можете указать специальный тег :hireswallclock для Benchmark (если Time::HiRes недоступен, тег будет проигнорирован). Этот тег заставит измерять время по часам в микросекундах вместо целых секунд. Однако следует учитывать, что вычисления скорости всё ещё проводятся в процессорном времени, а не во времени по часам.
Объект Benchmark
Многие функции в этом модуле возвращают объект Benchmark или, в случае timethese(), ссылку на хэш, значения которого являются объектами Benchmark. Это полезно, если вы хотите сохранить или дополнительно обработать результаты функций Benchmark.
Внутренне объект Benchmark хранит значения времени, описанные в разделе "ЗАМЕЧАНИЯ" ниже. Следующие методы можно использовать для доступа к ним:
- cpu_p
-
Общее процессорное время (пользователь + система) основного (родительского) процесса.
- cpu_c
-
Общее процессорное время (пользователь + система) любых дочерних процессов.
- cpu_a
-
Общее процессорное время родительского и всех дочерних процессов.
- real
-
Реальное время, прошедшее по часам.
- iters
-
Количество выполненных итераций.
Следующее иллюстрирует использование объекта Benchmark:
$result = timethis(100000, sub { ... });
print "total CPU = ", $result->cpu_a, "\n"; ЗАМЕЧАНИЯ
Данные хранятся как список значений из функций time и times:
($real, $user, $system, $children_user, $children_system, $iters) в секундах для всего цикла (не делённые на количество раундов).
Измерение времени выполняется с помощью time(3) и times(3).
Код выполняется в пакете вызывающего модуля.
Время нулевого цикла (цикла с тем же числом раундов, но пустым телом цикла) вычитается из времени реального цикла.
Времена нулевого цикла могут быть кэшированы, ключом является число раундов. Кэширование можно контролировать, используя такие вызовы:
clearcache($key);
clearallcache();
disablecache();
enablecache(); Кэширование отключено по умолчанию, поскольку оно (обычно немного) снижает точность и обычно не оказывает заметного влияния на время выполнения.
ПРИМЕРЫ
Например,
use Benchmark qw( cmpthese ) ;
$x = 3;
cmpthese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} ); выводит что-то вроде этого:
Benchmark: running a, b, each for at least 5 CPU seconds...
Rate b a
b 1559428/s -- -62%
a 4152037/s 166% -- в то время как
use Benchmark qw( timethese cmpthese ) ;
$x = 3;
$r = timethese( -5, {
a => sub{$x*$x},
b => sub{$x**2},
} );
cmpthese $r; выводит что-то вроде этого:
Benchmark: running a, b, each for at least 5 CPU seconds...
a: 10 wallclock secs ( 5.14 usr + 0.13 sys = 5.27 CPU) @ 3835055.60/s (n=20210743)
b: 5 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 1574944.92/s (n=8520452)
Rate b a
b 1574945/s -- -59%
a 3835056/s 144% -- НАСЛЕДОВАНИЕ
Benchmark не наследуется ни от какого другого класса, кроме, конечно, Exporter.
ОГРАНИЧЕНИЯ
Сравнение интерпретированных строк с ссылками на код даст вам неточные результаты: ссылка на код покажет немного более медленное время выполнения, чем эквивалентная интерпретированная строка.
Измерение реального времени выполняется с использованием time(2), поэтому точность составляет всего одну секунду.
Короткие тесты могут давать отрицательные значения, потому что Perl может показаться, что выполнение пустого цикла занимает больше времени, чем короткий тест; попробуйте:
timethis(100,'1'); Время системы нулевого цикла может быть немного больше, чем время системы цикла с фактическим кодом, и поэтому разница может оказаться < 0.
СМОТРИТЕ ТАКЖЕ
Devel::NYTProf - профайлер кода Perl
АВТОРЫ
Jarkko Hietaniemi <jhi@iki.fi>, Tim Bunce <Tim.Bunce@ig.co.uk>
История изменений
8 сентября 1994 г.; Тим Банс.
28 марта 1997 г.; Хьюго ван дер Санден: добавлена поддержка ссылок на код и уже документированный метод «debug»; переработана документация.
4-7 апреля 1997 г.: Ярко Хьетаниеми, добавлена функциональность выполнения некоторое время.
Сентябрь 1999 г.; Барри Слейтейкер: исправления математики, улучшения точности и эффективности. Добавлен cmpthese(). Теперь из timethese() возвращается результат. Доступна функция countit() (была runfor()).
Декабрь 2001 г.; Николас Кларк: функция timestr() теперь распознаёт стиль «none» и возвращает пустую строку. Если cmpthese вызывает timethese, передавайте стиль (чтобы «none» подавлял вывод). Подпрограмма new теперь выводит отладочные сообщения в STDERR для согласованности со всем остальным. Все найденные ошибки во время написания теста регрессии.
Сентябрь 2002 г.; Ярко Хьетаниеми: добавление специальной метки «:hireswallclock».
Февраль 2004 г.; Чья-лян Као: функции cmpthese и timestr используют статистику времени для дочерних элементов, а не родительских, когда стиль «nop».
Ноябрь 2007 г.; Кристоф Грошжан: функции cmpthese и timestr вычисляют время согласованно со значением аргумента стиля, по умолчанию «all», а не «noc».
© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/Benchmark