Spec-Zone.ru › Perl 5.28

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)

Функции вызываются в алфавитном порядке ключей.

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'ed строк со ссылками на код даст вам неточные результаты: ссылка на код покажет время выполнения чуть медленнее, чем эквивалентная строка 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.28.3/Benchmark

Spec-Zone.ru

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