Frage

Jedes Mal, wenn ich eine neue Kopie von Rakudo Perl 6 heruntergeladen haben, ich habe folgenden Ausdruck laufe nur eine Vorstellung von seiner aktuellen Leistung zu erhalten:

say [+] 1 .. 100000;

Und die Geschwindigkeiten wurden zu erhöhen, aber jedes Mal gibt es eine merkliche Verzögerung (mehrere Sekunden) für die Berechnung. Als Vergleich, so etwas wie dies in Perl 5 (oder andere interpretierten Sprachen) gibt fast sofort:

use List::Util 'sum';

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

oder in Ruby (auch fast sofort):

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

Umschreiben der Ausdruck als Perl6 loop endet etwa doppelt so schnell ist wie die Bandbreite zu reduzieren, aber es ist immer noch eine sehr merkliche Verzögerung (mehr als eine Sekunde) für die einfache Berechnung:

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

Also meine Frage ist, welche Aspekte der Perl6 Implementierung verursachen diese Performance-Probleme? Und soll dies mit der Zeit verbessern, oder ist dieser Aufwand ein unglücklicher Nebeneffekt des „alles ein Objekt“ -Modell, dass Perl6 verwendet?

Und schließlich, was ist mit dem loop Konstrukt ist schneller als der [+] Reduktionsoperator? Ich würde denken, dass die Schleife in insgesamt mehr ops als die Reduktion führen würde.

EDIT:

Ich würde beide akzeptieren mortiz ist und hobbs die Antworten, wenn ich könnte. Das alles wird als ein Methodenaufruf behandelt mehr ein Wesen direkt beantwortet, warum [+] wird langsam zu sein, so dass man es bekommt.

War es hilfreich?

Lösung

Eine andere Sache, die Sie haben über den Mangel an Optimierung zu verstehen ist, dass es uns geklammerten . Ein großer Teil der Rakudo geschrieben in Perl 6 . So zum Beispiel der Operator [+] durch das Verfahren Any.reduce (genannt mit $expression Satz &infix:<+>) implementiert ist, die als ihre innere Schleife

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

mit anderen Worten, ein reines-perl Implementierung zu reduzieren, was sich durch Rakudo ausgeführt wird. So wird nicht nur der Code, den Sie können sehen nicht optimiert zu werden, wird der Code, dass Sie nicht sehen, dass der Code laufen zu machen ist auch nicht immer optimiert. Auch Instanzen des + Betreiber sind tatsächlich Anrufe Methode, da obwohl die + Betreiber auf Num von Parrot implementiert ist, zu erkennen, noch nichts in Rakudo gibt es, dass Sie zwei Nums haben und optimize der Aufruf der Methode entfernt, so gibt es eine vollständige dynamische Dispatch vor Rakudo findet multi sub infix:<+>(Num $a, Num $b) und erkennt, dass alle es ist wirklich ein ‚add‘ opcode tun ist. Es ist eine vernünftige Entschuldigung für sein 100-1000x langsamer als Perl 5:)

Update 2010.08.23

Weitere Informationen von Jonathan Worthington das muss mit dem Perl-6-Objektmodell passieren (oder Rakudo Konzeption der es zumindest), um die Dinge schnell zu machen unter Beibehaltung Perl 6 ist „alles ist Methodenaufrufe“ Natur.

Update 2019.01.10

Da ich sehen kann, dass dies immer noch Aufmerksamkeit bekommen ... im Laufe der Jahre, Rakudo / MoarVM JIT bekommen hat, inlining, dynamische Spezialisierung und t die Arbeit von vielen Menschen jeden Teils der Optimierung das System. Das Ergebnis ist, dass die meisten dieser Methodenaufrufe können „zusammengestellt aus“ und fast Null Laufzeit Kosten haben werden. Perl 6 Partituren hunderte oder tausende Male schneller auf vielen Benchmarks, als es im Jahr 2010 getan hatte, und in einigen Fällen ist es schneller als Perl 5.

Bei der Summe zu 100.000 Problem, dass die Frage begann mit, Rakudo 2.018,06 ist immer noch ein bisschen langsamer als 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

Aber wenn wir Start Kosten amortisieren, indem der Code 10.000 Mal ausgeführt wird, finden wir eine andere Geschichte:

$ 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 verwendet ein paar hundert mehr Millisekunden als perl5 beim Start und Zusammenstellung, aber dann rechnet sie heraus, wie die tatsächliche Summe tun etwa 70-mal schneller.

Andere Tipps

Es gibt wirklich verschiedene Gründe, warum Rakudo so langsam ist.

Der erste und vielleicht wichtigste Grund ist, dass Rakudo keine Optimierungen noch tut. Die aktuellen Ziele auszuloten, neue Funktionen und robuster werden. Sie wissen, sagen sie „zuerst machen es laufen, dann ist es richtig zu machen, dann ist es schnell machen“.

Der zweite Grund ist, dass Papagei keine JIT-Kompilierung noch bietet, und der Garbage Collector ist nicht der schnellste. Es gibt Pläne für einen JIT-Compiler und die Leute arbeiten daran (der vorherige wurde herausgerissen, weil es i386 war nur und Wartung Alptraum). Es gibt auch Gedanken von Rakudo zu anderen VMs zu portieren, aber das wird sicher bis nach dem Ende Juli warten.

Am Ende kann niemand wirklich sagen, wie schnell eine vollständige, gut optimierte Perl 6 Implementierung, bis wir eine haben, aber ich erwarte es viel besser sein als jetzt.

BTW der Fall, dass Sie zitiert [+] 1..$big_number gemacht werden könnten in O (1), weil 1..$big_number kehrt ein Range, laufen die introspectable ist. So können Sie eine Summenformel für den [+] Range Fall verwenden. Wieder etwas, das es ist, was getan werden könnte, aber das noch nicht geschehen ist.

Es ist sicher nicht, weil alles ist ein Objekt , denn das ist wahr in einer Reihe von anderen Sprachen zu (wie Ruby). Es gibt keinen Grund, warum Perl 6 haben würde Größenordnung langsamer als andere Sprachen wie Perl 5 oder Ruby, aber die Tatsache ist, dass Rakudo nicht wie Perl oder CRuby reifen wird. Es wurde viel Geschwindigkeitsoptimierung noch nicht gewesen.

In Anbetracht, dass jetzt Ihr Testfall ist optimiertem zu einem O (1) Algorithmus , dass fast sofort zurückkehrt, und dass es fast wie gibt es mehrere Optimierungen in der Woche scheint;
Ich erwarte eine sehr Leistungssteigerung rundum.

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

Auch wenn das nicht besondere Gefasste für Bereiche ist es immer noch ziemlich viel schneller, als es war.
Jetzt ist Ihre Testberechnung in weniger als ein Fünftel einer Sekunde.

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

Ich legte diese Fefe Sprache Wettbewerb im Dezember 2008. wp.pugs.pl eine wörtliche Übersetzung des Perl 5 Beispiel ist wp.rakudo.pl weit mehr sixier. Ich habe zwei Programme, weil die beiden eine andere Teilmenge der Spezifikation implementieren. Build-Informationen ist mittlerweile veraltet. Die Quellen:

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

Dies waren die Ergebnisse im Jahr 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

Heute:

$ 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

Späte Ergänzungen: Der Absturz hat unter behandelt worden, warum ich divide erhalte‘durch zero` Fehler, wenn ich versuche meinen Skript mit Rakudo laufen ? . Das Rakudo Programm ist ineffizient finden Sie unter Kommentaren unten und http://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/ .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top