Какого повышения производительности мы можем ожидать по мере развития Perl 6? - PullRequest
27 голосов
/ 28 июня 2010

Каждый раз, когда я загружал новую копию Rakudo Perl 6, я запускал следующее выражение, чтобы просто получить представление о его текущей производительности:

say [+] 1 .. 100000;

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

use List::Util 'sum';

print sum(1 .. 100000), "\n";

или в Ruby (также почти мгновенно):

(1 .. 100000).inject(0) {|sum,x| sum+x}

Переписывание выраженияпоскольку Perl6 loop заканчивается примерно вдвое быстрее, чем уменьшение диапазона, но это все еще очень заметная задержка (более секунды) для простого вычисления:

my $sum;
loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}

Так что мой вопросКакие аспекты реализации Perl6 вызывают эти проблемы с производительностью?И должно ли это со временем улучшиться, или это накладные расходы, к сожалению, побочный эффект модели «все является объектом», которую использует Perl6?

И, наконец, что с конструктом loop быстрее, чем оператор сокращения [+]?Я думаю, что цикл приведет к большему количеству операций, чем к сокращению.

РЕДАКТИРОВАТЬ:

Я бы принял ответы mortiz и hobbs, если бы мог,То, что все обрабатывается как вызов метода, более прямо объясняет, почему [+] медленный, так что его можно получить.

Ответы [ 5 ]

22 голосов
/ 29 июня 2010

Есть действительно различные причины, по которым Rakudo такой медленный.

Первая и, возможно, самая важная причина в том, что Rakudo пока не проводит никаких оптимизаций.Текущие цели - больше исследовать новые функции и стать более надежными.Вы знаете, они говорят: «сначала запустите его, затем сделайте это правильно, затем сделайте это быстро».

Вторая причина в том, что попугай еще не предлагает JIT-компиляцию, а сборщик мусора - нетсамый быстрый.Есть планы для JIT-компилятора, и люди работают над ним (предыдущий был разорван, потому что это был только i386 и кошмар обслуживания).Есть также мысли о переносе Rakudo на другие виртуальные машины, но это наверняка подождет до конца июля.

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

Кстати, приведенный вами случай [+] 1..$big_number может быть выполнен для запуска в O (1), потому что 1..$big_number возвращает Range,что самоанализТаким образом, вы можете использовать формулу суммы для случая [+] Range.Опять же, это то, что можно сделать, но это еще не сделано.

17 голосов
/ 29 июня 2010

Еще одна вещь, которую вы должны понять об отсутствии оптимизации, это то, что она составлена ​​. Большая часть Rakudo написана на Perl 6 . Так, например, оператор [+] реализуется методом Any.reduce (вызывается с $expression, установленным в &infix:<+>), который имеет в качестве внутреннего цикла

for @.list {
    @args.push($_);
    if (@args == $arity) {
        my $res = $expression.(@args[0], @args[1]);
        @args = ($res);
    }
}

Другими словами, реализация Reduce, основанная исключительно на Perl, которая сама управляется Rakudo. Так что не только код, который вы можете увидеть , не оптимизируется, но и код, который вы не видите, который заставляет работать ваш код, также не получает оптимизировано. Даже экземпляры оператора + на самом деле являются вызовами методов, так как хотя оператор + в Num реализован в Parrot, в Rakudo еще нет ничего, чтобы распознать, что у вас есть два Num s, и оптимизировать их. вызов метода, поэтому перед тем, как Ракудо обнаружит multi sub infix:<+>(Num $a, Num $b) и поймет, что все, что он на самом деле делает - это добавляет код операции добавления, происходит полная динамическая отправка. Это разумное оправдание для того, чтобы быть в 100-1000 раз медленнее, чем Perl 5:)

Обновление 8/23 / 2010

Дополнительная информация от Джонатана Уортингтона о тех изменениях, которые должны произойти с объектной моделью Perl 6 (или, по крайней мере, с точки зрения ее концепции Ракудо), чтобы ускорить процесс, сохранив при этом Perl 6 "все - метод называет "природой".

Обновление 1/10/2019

Так как я вижу, что это все еще привлекает внимание ... за эти годы Rakudo / MoarVM получили JIT, встраивание, динамическую специализацию и тонн работы многими людьми, оптимизирующими каждую часть система. В результате большинство из этих вызовов методов могут быть «скомпилированы» и иметь практически нулевые затраты времени выполнения. Perl 6 набирает в сотни или тысячи раз быстрее по многим тестам, чем в 2010 году, а в некоторых случаях он быстрее, чем Perl 5.

В случае проблемы с суммой в 100 000, с которой начался вопрос, Rakudo 2018.06 все еще немного медленнее, чем perl 5.26.2:

$ time perl -e 'use List::Util 'sum'; print sum(1 .. 100000), "\n";' >/dev/null

real    0m0.023s
user    0m0.015s
sys     0m0.008s

$ time perl6 -e 'say [+] 1 .. 100000;' >/dev/null

real    0m0.089s
user    0m0.107s
sys     0m0.022s

Но если мы амортизируем стоимость запуска, выполнив код 10 000 раз, мы увидим другую историю:

$ time perl -e 'use List::Util 'sum'; for (1 .. 10000) { print sum(1 .. 100000), "\n"; }' > /dev/null

real    0m16.320s
user    0m16.317s
sys     0m0.004s

$ time perl6 -e 'for 1 .. 10000 { say [+] 1 .. 100000; }' >/dev/null

real    0m0.214s
user    0m0.245s
sys     0m0.021s

perl6 использует на несколько сотен миллисекунд больше, чем perl5, при запуске и компиляции, но затем он выясняет, как выполнить фактическое суммирование примерно в 70 раз быстрее.

5 голосов
/ 29 июня 2010

Конечно, это не потому, что все является объектом , потому что это верно и для ряда других языков (например, Ruby).Нет никаких причин, почему Perl 6 должен был бы быть на несколько медленнее, чем другие языки, такие как Perl 5 или Ruby, но факт в том, что Rakudo не настолько зрел, как Perl или CRuby.Оптимизация скорости пока не проводилась.

4 голосов
/ 18 ноября 2015

Учитывая, что теперь ваш тестовый пример оптимизирован для алгоритма O (1) , который возвращается почти мгновенно, и кажется, что в неделю происходит несколько оптимизаций; * Я ожидаю значительное улучшение производительности вокруг.

$ perl6 -e 'say [+] 1..10**1000; say now - INIT now'
5000000000000000000000000000000000000000000000 ...
0.007447

Даже если это не было специального случая для диапазонов, оно все равно немного быстрее, чем было.
Теперь он выполняет ваш тестовый расчет менее чем за одну пятую секунды.

$ perl6 -e 'say [+] (1..100000).list; say now - INIT now'
5000050000
0.13052975
3 голосов
/ 29 июня 2010

Я отправил их на языковой конкурс Fefe в декабре 2008 года. wp.pugs.pl - дословный перевод примера Perl 5, wp.rakudo.pl - намного более шестерка. У меня есть две программы, потому что они реализуют разные подмножества спецификации. Информация о сборке устарела. Источники:

#!/usr/bin/env pugs
# Pugs: <http://pugs.blogs.com/> <http://pugscode.org/>
# prerequisite: ghc-6.8.x, not 6.10.x
# svn co http://svn.pugscode.org/pugs/
# perl Makefile.PL
# make
# if build stops because of haskeline, do:
#   $HOME/.cabal/bin/cabal update ; $HOME/.cabal/bin/cabal install haskeline

# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>

my %words;

for =<> {
    for .split {
        %words{$_}++
    }
}

for (sort { %words{$^b} <=> %words{$^a} }, %words.keys) {
    say "$_ %words{$_}"
}

#!/usr/bin/env perl6
# Rakudo: <http://rakudo.org/> <http://www.parrot.org/download>
# svn co http://svn.perl.org/parrot/trunk parrot
# perl Configure.pl
# make perl6

# Solution contributed by Frank W. & Moritz Lenz
# <http://use.perl.org/~fw/journal/38055>
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>

my %words;

$*IN.lines.split(/\s+/).map: { %words{$_}++ };

for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair {
    say $pair
}

Это были результаты 2008 года:

$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo

real    0m2.529s
user    0m2.464s
sys     0m0.064s

$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo

real    0m32.544s
user    0m1.920s
sys     0m0.248s

Сегодня:

$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo

real    0m5.105s
user    0m4.898s
sys     0m0.096s

$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
Divide by zero
current instr.: '' pc -1 ((unknown file):-1)
Segmentation fault

real    0m3.236s
user    0m0.447s
sys     0m0.080s

Позднее добавление: Сбой произошел в Почему я получаю ошибки «делим на ноль», когда пытаюсь запустить свой скрипт с Rakudo? . Программа Rakudo неэффективна, см. комментарии ниже и http://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/.

...