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 может быть либо ссылкой на код, либо строкой для eval; в любом случае он будет выполнен в пакете вызывающей программы.
Возвращает: объект Benchmark.
- timethis ( COUNT, CODE, [ TITLE, [ STYLE ]] )
-
Измеряет время выполнения COUNT итераций CODE. CODE может быть строкой для eval или ссылкой на код; в любом случае код будет выполнен в пакете вызывающей программы. Результаты будут выведены в 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 - ссылка на массив, содержащий имена в качестве ключей и либо строку для eval, либо ссылку на код для каждого значения. Для каждой пары (KEY, VALUE) в CODEHASHREF эта процедура вызовет
timethis(COUNT, VALUE, KEY, STYLE)Процедуры вызываются в порядке строчного сравнения ключей.
COUNT может быть нулём или отрицательным, см. timethis().
Возвращает ссылку на массив объектов Benchmark, индексированных по имени.
- timediff ( T1, T2 )
-
Возвращает разницу между двумя временами Benchmark как объект Benchmark, подходящий для передачи в timestr().
- timestr ( TIMEDIFF, [ STYLE, [ FORMAT ] ] )
-
Возвращает строку, форматирующую времена в объекте TIMEDIFF в запрошенном стиле STYLE. TIMEDIFF ожидается как объект Benchmark, аналогичный тому, который возвращается timediff().
STYLE может принимать значения 'all', 'none', 'noc', 'nop' или 'auto'. 'all' отображает все 5 доступных времён ('wallclock' time, время пользователя, время системы, время пользователя дочерних процессов и время системы дочерних процессов). 'noc' отображает все, кроме двух времён дочерних процессов. 'nop' отображает только время wallclock и два времени дочерних процессов. '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 может быть либо ссылкой на код, либо строкой для eval; в любом случае он будет выполнен в пакете вызывающей программы.
TIME не является отрицательным числом. countit() многократно выполнит цикл для расчета скорости CODE перед выполнением его на время TIME. Фактическое время выполнения обычно будет больше TIME из-за разрешения системных часов, поэтому лучше всего смотреть на количество итераций, деленное на время, которое вас интересует, а не просто на количество итераций.
Возвращает объект Benchmark.
- disablecache ( )
-
Отключить кэширование времени для пустого цикла. Это заставит Benchmark пересчитывать эти времена для каждого нового фрагмента кода.
- enablecache ( )
-
Включить кэширование времени для пустого цикла. Время, затраченное на COUNT циклов пустого цикла, будет вычислено только один раз для каждого используемого COUNT.
- timesum ( T1, T2 )
-
Возвращает сумму двух времён Benchmark в виде объекта Benchmark, подходящего для передачи в timestr().
:hireswallclock
Если модуль Time::HiRes установлен, вы можете указать специальный тег :hireswallclock для Benchmark (если Time::HiRes недоступен, тег будет проигнорирован). Этот тег заставит измерять время wallclock в микросекундах вместо целых секунд. Однако обратите внимание, что вычисления скорости по-прежнему проводятся по времени CPU, а не по времени wallclock.
Объект Benchmark
Многие функции в этом модуле возвращают объект Benchmark, или в случае timethese(), ссылку на массив, значениями которого являются объекты Benchmark. Это полезно, если вы хотите сохранить или дополнительно обработать результаты функций Benchmark.
Внутри объект Benchmark хранит значения времени, описанные в "ПРИМЕЧАНИЯ" ниже. Следующие методы могут использоваться для доступа к ним:
- cpu_p
-
Общее время CPU (пользователь + система) основного (родительского) процесса.
- cpu_c
-
Общее время CPU (пользователь + система) всех дочерних процессов.
- cpu_a
-
Общее время CPU родительского и всех дочерних процессов.
- real
-
Фактическое время выполнения (секунды wallclock).
- 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.
ОГРАНИЧЕНИЯ
Сравнение строк eval'd со ссылками на код даст вам неточные результаты: ссылка на код покажет немного более медленное время выполнения, чем эквивалентная строка eval'd.
Измерение реального времени выполняется с использованием time(2), и поэтому точность составляет только одну секунду.
Короткие тесты могут давать отрицательные значения, поскольку Perl может, по-видимому, тратить больше времени на выполнение пустого цикла, чем на короткий тест; попробуйте:
timethis(100,'1'); Время системы пустого цикла может быть немного больше, чем время системы цикла с фактическим кодом, и поэтому разница может оказаться < 0.
СМОТРИТЕ ТАКЖЕ
Devel::NYTProf - профайлер кода Perl
АВТОРЫ
Jarkko Hietaniemi <jhi@iki.fi>, Tim Bunce <Tim.Bunce@ig.co.uk>
История изменений
8 сентября 1994 г.; Tim Bunce.
28 марта 1997 г.; Hugo van der Sanden: добавлена поддержка ссылок на код и уже задокументированный метод 'debug'; переработана документация.
4–7 апреля 1997 г.: Jarkko Hietaniemi, добавлена возможность выполнения на некоторое время.
Сентябрь 1999 г.; Barrie Slaymaker: исправления в математике, улучшения точности и эффективности. Добавлена функция cmpthese(). Теперь функция timethese() возвращает результат. Доступна функция countit() (была runfor()).
Декабрь 2001 г.; Nicholas Clark: функция timestr() теперь распознаёт стиль 'none' и возвращает пустую строку. Если cmpthese вызывает timethese, передавать стиль (чтобы стиль 'none' подавлял вывод). Функция sub теперь выводит отладочную информацию в STDERR, чтобы быть согласованной со всем остальным. Все ошибки, обнаруженные при написании регрессионного теста.
Сентябрь 2002 г.; Jarkko Hietaniemi: добавление специальной метки ':hireswallclock'.
Февраль 2004 г.; Chia-liang Kao: функции cmpthese и timestr используют статистику времени для потомков вместо родительского элемента, когда стиль 'nop'.
Ноябрь 2007 г.; Christophe Grosjean: функции cmpthese и timestr вычисляют время последовательно со значением аргумента style, по умолчанию 'all', а не 'noc'.
© 1993–2021 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.36.0/Benchmark