понедельник, 5 ноября 2007 г.

Сравнение производительности perl кода

Иногда требуется выяснить как быстро работает тот или иной фрагмент кода на perl. Для этого можно использовать perl модуль Benchmark, входящий в стандартную поставку perl.

Задача. Как оптимальнее организовать перебор элементов хеша, например просуммировать значения всех ключей. В полном соответствии с принципом TIMTOWTDI существует несколько вариантов решения задачи:

Вариант №1. Использование цикла «foreach ( values ... )».

sub hash_values_sum_1(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ foreach values %hash;
    return $sum;
}

Вариант №2. Использование конструкции«map ... values ... ».

sub hash_values_sum_2(%) {
    my %hash = @_;
    my $sum = 0;
    map { $sum += $_ } values %hash;
    return $sum;
}

Вариант №3. Использование цикла «while ( ... each ... )».

sub hash_values_sum_3(%) {
    my %hash = @_;
    my $sum = 0;
    $sum += $_ while (undef, $_) = each %hash;
    return $sum;
}

Для проверки проверки напишем небольшой тестовый скрипт:

#!/usr/bin/perl -w
use strict;
use Benchmark qw/ :all /;

my %hash = map { rand, rand } ( 1 .. 1000 );

cmpthese( 5_000_000 , {
    var1 => 'my $sum = 0; $sum += $_ foreach values %hash',
    var2 => 'my $sum = 0; map { $sum += $_ } values %hash;',
    var3 => 'my $sum = 0; $sum += $_ while (undef, $_) = each %hash;',
} );

Проверяем производительность трех вариантов решения задачи. Для этого используем тестовый хеш, содержащий 1000 случайных ключей со случайными значениями. Для получения усредненных результатов, каждый из вариантов запускается по 5 миллионов раз. Результаты работы скрипта:

          Rate variant_1 variant_3 variant_2
var1  946970/s        --      -48%      -73%
var3 1838235/s       94%        --      -48%
var2 3546099/s      274%       93%        --

По таблице результатов видно, что:

  1. Вариант №3 работает почти в 2 раза быстрее, чем вариант №1.
  2. Вариант №2 работает почти в 2 раза быстрее, чем вариант №3.

В данном конкретном случае вариант №2 является однозначным победителем. Его использование более предпочтительно.

Комментариев нет: