Иногда требуется выяснить как быстро работает тот или иной фрагмент кода на 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% --
По таблице результатов видно, что:
- Вариант №3 работает почти в 2 раза быстрее, чем вариант №1.
- Вариант №2 работает почти в 2 раза быстрее, чем вариант №3.
В данном конкретном случае вариант №2 является однозначным победителем. Его использование более предпочтительно.