Perl - статьи


         

Не оптимизируйте код -- замеряйте его производительность!


Если Вам нужна функция для удаления дублирующихся элементов массива, вполне естественно, что однострочная версия наподобие этой:

sub uniq { return keys %{ { map {$_ => 1} @_ } } }

будет более эффективна, чем два оператора:

sub uniq { my %seen; return grep {!$seen{$_}++} @_; }

До тех пор пока Вы не будете глубоко знакомы с внутренностями Perl-интерпретатора (а в этом случае Вы наверняка уже будете решать вопросы посложнее), интуиция по поводу относительного быстродействия двух конструкций является ничем иным как неосознанным выбором.

Единственный способ узнать какая из двух альтернатив быстрее — замерить каждую из них. Со стандартным модулем Benchmark это просто:

# Короткий список не-совсе-уникальных значений... our @data = qw( do re me fa so la ti do );

# Различные кандидаты... sub unique_via_anon { return keys %{ { map {$_ => 1} @_ } }; }

sub unique_via_grep { my %seen; return grep { !$seen{$_}++ } @_; }

sub unique_via_slice { my %uniq; @uniq{ @_ } = (); return keys %uniq; }

# Сравнить, используя текущий набор данных из @data... sub compare { my ($title) = @_; print "\n[$title]\n";

# Создать сравнительную таблицу различных замеров времени, # при том, чтобы каждый запуск продолжался минимум 10 секунд... use Benchmark qw( cmpthese ); cmpthese -10, { anon => 'my @uniq = unique_via_anon(@data)', grep => 'my @uniq = unique_via_grep(@data)', slice => 'my @uniq = unique_via_slice(@data)', };

return; }

compare('8 элементов, 10% повторяющихся');

# Зве копии исходных данных... @data = (@data) x 2; compare('16 элементов, 56% повторяющихся');

# Сто копий исходных данных... @data = (@data) x 50; compare('800 элементов, 99% повторяющихся');

Процедура cmpthese() принимает в качестве аргумента число и далее ссылку на хэш с тестами. Число обозначает либо точное число запусков каждого теста (если это число положительное), либо количество секунд процессорного времени, в течение которого нужно гонять каждый тест (если число отрицательное). Обычные используемые значения — примерно 10'000 повторений или 10 CPU-секунд, но модуль предупредит Вас если тест будет слишком коротким для получения точного замера.



Содержание  Назад  Вперед