Еще одна вещь, которую вы должны понять об отсутствии оптимизации, это то, что она составлена . Большая часть 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 раз быстрее.