Question

Chaque fois que j'ai téléchargé une nouvelle copie de Rakudo Perl 6, j'ai couru l'expression suivante juste pour avoir une idée de sa performance actuelle:

say [+] 1 .. 100000;

Et les vitesses ont augmenté, mais à chaque fois, il y a un retard notable (plusieurs secondes) pour le calcul. A titre de comparaison, quelque chose comme ça en Perl 5 (ou d'autres langues interprétées) retourne presque instantanément:

use List::Util 'sum';

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

ou Ruby (aussi presque instantanée):

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

Réécrire l'expression comme extrémités de loop Perl6 par être environ deux fois plus vite que la réduction de la gamme, mais il est encore un retard très sensible (plus d'une seconde) pour le calcul simple:

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

Alors, ma question est, quels sont les aspects de la mise en œuvre Perl6 sont à l'origine de ces problèmes de performance? Et si cela s'améliorer avec le temps, ou est-ce au-dessus d'un effet secondaire malheureux du modèle « tout est un objet » que Perl6 utilise?

Et enfin, qu'en la construction loop est plus rapide que l'opérateur de réduction de [+]? Je pense que la boucle entraînerait ops plus au total que la réduction.

EDIT:

J'accepte les deux de la mortiz et les réponses de hobbs si je pouvais. Que tout est un être traité comme un appel de méthode plus répond directement pourquoi [+] est d'être lent, de sorte que l'on obtient.

Était-ce utile?

La solution

Une autre chose que vous devez comprendre au sujet du manque d'optimisation est qu'il est COMPOSÉ . est écrit une grande partie de Rakudo en Perl 6 . Ainsi, par exemple l'opérateur de [+] est mis en oeuvre par le procédé Any.reduce (appelée avec jeu de $expression à &infix:<+>), qui a pour boucle interne

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

autrement dit, une mise en œuvre pure perl de réduire, ce qui est lui-même dirigé par Rakudo. Ainsi, non seulement est le code que vous pouvez voir Ne pas obtenir optimisé, le code que vous ne pas voyez que de faire tourner votre code est également ne reçoit pas optimisé. instances même de l'opérateur + sont en fait des appels de méthode, car, bien que l'opérateur + sur Num est mis en œuvre par Parrot, il n'y a rien encore Rakudo de reconnaître que vous avez deux Nums et optimize loin l'appel de méthode, donc il y a une dépêche de dynamique complète avant Rakudo trouve multi sub infix:<+>(Num $a, Num $b) et se rend compte que tout cela fait vraiment est un opcode « ajouter ». Il est une excuse raisonnable pour être 100-1000x plus lent que Perl 5:)

Mise à jour 8/23/2010

Plus d'informations de Jonathan Worthington sur les types de changements qui doivent se produire avec le modèle objet Perl 6 (ou au moins la conception de Rakudo de celui-ci) pour faire les choses rapidement tout en conservant la nature « tout est appels de méthode » de Perl 6.

Mise à jour 10/01/2019

Depuis que je peux voir que cela encore ... pour attirer l'attention au fil des ans, Rakudo / MoarVM ont obtenu JIT, inline, spécialisation dynamique et tonnes de travail par beaucoup de gens optimiser chaque partie le système. Le résultat est que la plupart de ces appels de méthode peut être « compilé sur » et ont presque zéro coût d'exécution. cliquer ici Perl 6 des centaines ou des milliers de fois plus rapide sur de nombreux points de référence qu'il a fait en 2010, et dans certains cas, il est plus rapide que Perl 5.

Dans le cas du problème somme à 100 000 que la question a commencé avec, Rakudo 2018,06 est encore un peu plus lent que 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

Mais si nous amortissons sur les coûts de démarrage en exécutant le code 10000 fois, nous voyons une autre histoire:

$ 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 utilise quelques centaines de millisecondes plus que perl5 au démarrage et la compilation, mais il figure comment faire la somme réelle environ 70 fois plus rapide.

Autres conseils

Il y a vraiment diverses raisons pour lesquelles Rakudo est si lent.

La première et peut-être plus importante raison est que Rakudo ne fait aucune optimisations encore. Les objectifs actuels sont plus explorent de nouvelles fonctionnalités, et de devenir plus robuste. Vous savez, ils disent « d'abord le faire fonctionner, puis le faire à droite, puis le faire rapidement ».

La deuxième raison est que le perroquet ne propose pas encore de compilation JIT, et le garbage collector est pas le plus rapide. Il y a des plans pour un compilateur JIT, et les gens y travaillent (le précédent a été arraché parce qu'il était i386 et un cauchemar de maintenance). Il y a aussi des pensées de portage Rakudo à d'autres machines virtuelles, mais qui vont sûrement attendre jusqu'à après la fin de Juillet.

En fin de compte, personne ne peut vraiment dire à quelle vitesse une complète, la mise en œuvre Perl 6 bien optimisé sera jusqu'à ce que nous avons, mais je ne pensais que ce serait beaucoup mieux que maintenant.

BTW le cas que vous avez cité [+] 1..$big_number pourrait être fait pour fonctionner en O (1), parce que les rendements de 1..$big_number une plage, qui est introspecter. Vous pouvez donc utiliser une formule de somme pour le cas [+] Range. Encore une fois, il y a quelque chose qui pourrait être fait, mais cela n'a pas encore été fait.

Il est certainement pas parce que tout est un objet , parce que c'est vrai dans un certain nombre d'autres langues (comme Ruby). Il n'y a aucune raison pour laquelle Perl 6 devrait être magnitudes plus lent que d'autres langages comme Perl 5 ou Ruby, mais le fait est que Rakudo est pas aussi mature que perl ou CRuby. Il n'a pas encore été beaucoup optimisation de la vitesse.

Considérant maintenant votre cas de test est optimisé pour un O (1) algorithme que les rendements presque instantanément, et qu'il semble presque comme il y a plusieurs optimisations par semaine;
Je pense tout à fait une amélioration de la performance tout autour.

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

Même si cela n'a pas été spécial tubé pour les plages, il est encore un peu plus rapide que c'était.
Il fait maintenant votre calcul de test en moins d'un cinquième de seconde.

$ perl6 -e 'say [+] (1..100000).list; say now - INIT now'
5000050000
0.13052975

Je soumis ces concours des langues Fefe en Décembre 2008. wp.pugs.pl est une traduction littérale de l'exemple Perl 5, wp.rakudo.pl est beaucoup plus sixier. J'ai deux programmes parce que les deux sous-ensemble mettre en œuvre un autre de la spécification. informations de construction est obsolète quant à lui. Les sources:

#!/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
}

Ce sont les résultats en 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

Aujourd'hui:

$ 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

additions tardives: Le crash a été traité Pourquoi est-ce que je reçois « diviser par zero` erreurs lorsque je tente de lancer mon script avec Rakudo . Le programme Rakudo est inefficace, voir et http://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/ .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top