Spec-Zone.ru › Perl 5.34

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

Объект 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–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.34.0/Benchmark

Spec-Zone.ru

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