Spec-Zone.ru › Perl 5.30

Benchmark

СОДЕРЖАНИЕ

  • ИМЯ
  • СИНТАКСИС
  • ОПИСАНИЕ
    • Методы
    • Стандартные Экспорты
    • Дополнительные Экспорты
    • :hireswallclock
  • Объект 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, или ссылкой на код; в любом случае код выполняется в пакете вызывающей функции. Результаты выводятся в стандартный вывод в виде 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)

Процедуры вызываются в лексикографическом порядке строк KEY.

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', время пользователя, время системы, время пользователя дочерних процессов и время системы дочерних процессов). '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 может быть либо ссылкой на код, либо строкой, подлежащей 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 недоступен, тег будет проигнорирован). Этот тег заставит измерение системного времени в микросекундах вместо целых секунд. Однако следует помнить, что вычисления скорости всё ещё выполняются в процессорном времени, а не в системном.

Объект 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.

ЗАМЕЧАНИЯ

Сравнение строк eval с ссылками на код даст вам неточные результаты: ссылка на код покажет время выполнения немного медленнее, чем эквивалентная строка eval.

Измерение реального времени выполняется с использованием 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»). Подпрограмма new теперь выводит отладочную информацию в STDERR, чтобы соответствовать остальным функциям. Исправлены все ошибки, найденные при написании тестового набора.

Сентябрь 2002 года; Jarkko Hietaniemi: добавление специальной метки «:hireswallclock».

Февраль 2004 года; Chia-liang Kao: функции cmpthese и timestr используют статистику времени для дочерних процессов вместо родительского, когда стиль «nop».

Ноябрь 2007 года; Christophe Grosjean: функции cmpthese и timestr вычисляют время согласованно со значением аргумента стиля, по умолчанию «all», а не «noc».

© 1993–2020 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.30.3/Benchmark

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API