Domanda

Ogni volta che ho scaricato una nuova copia di Rakudo Perl 6, ho eseguito la seguente espressione solo per avere un'idea delle sue prestazioni attuali:

say [+] 1 .. 100000;

E i costi sono aumentati, ma ogni volta, c'è un ritardo notevole (alcuni secondi) per il calcolo. A titolo di confronto, qualcosa di simile a Perl 5 (o altri linguaggi interpretati) restituisce quasi immediatamente:

use List::Util 'sum';

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

o in rubino (anche quasi istantanea):

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

Riscrittura l'espressione come un Perl6 estremità loop per essere circa due volte più veloce riducendo la portata, ma è ancora un ritardo molto evidente (più di un secondo) per il calcolo semplice:

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

Quindi la mia domanda è, cosa aspetti dell'attuazione Perl6 stanno causando questi problemi di prestazioni? E questo dovrebbe migliorare con il tempo, o è questo overhead un effetto collaterale del "tutto è un oggetto" modello che Perl6 sta usando?

E, infine, per quanto riguarda il costrutto loop è più veloce l'operatore di riduzione [+]? Vorrei pensare che il ciclo si tradurrebbe in ops più totale rispetto della riduzione.

EDIT:

Mi piacerebbe accettare sia di mortiz e se potessi le risposte di hobbs. Che tutto è un essere gestita come una chiamata di metodo più diretto Risposte Perché [+] è essere lento, in modo che si ottiene.

È stato utile?

Soluzione

Un'altra cosa che dovete capire circa la mancanza di ottimizzazione è che si tratta di aggravata . Una gran parte di Rakudo è scritto in Perl 6 . Così per esempio l'operatore [+] è implementato il metodo Any.reduce (chiamato con $expression set di &infix:<+>), che ha come ciclo interno

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

in altre parole, un'implementazione pura Perl di ridurre, che a sua volta è gestito da Rakudo. Quindi non solo è il codice è possibile vedere non ottenere ottimizzati, il codice che si non vedere che sta facendo la corsa codice non è anche sempre ottimizzato. istanze Anche dell'operatore + sono in realtà chiamate a metodi, in quanto anche se l'operatore + su Num è implementato da Parrot, non c'è ancora nulla in Rakudo di riconoscere che hai due Nums e ottimizzare via la chiamata di metodo, quindi non c'è un dispaccio piena dinamica prima Rakudo trova multi sub infix:<+>(Num $a, Num $b) e si rende conto che tutto quello che sta realmente facendo è un codice operativo 'add'. E 'una scusa ragionevole per essere 100-1000x più lento di Perl 5:)

Aggiornamento 2010/08/23

Maggiori informazioni da Jonathan Worthington sul tipo di cambiamenti che devono accadere con il modello a oggetti Perl 6 (o almeno la concezione di Rakudo di esso) per rendere le cose velocemente, pur mantenendo Perl 6 del "tutto è chiamate di metodo" la natura.

Aggiornamento 2019/01/10

Dato che posso vedere che questo è ancora ottenendo l'attenzione ... nel corso degli anni, Rakudo / MoarVM hanno ottenuto JIT, inlining, la specializzazione dinamica, e tonnellate di lavoro da parte tante persone ottimizzando ogni parte del il sistema. Il risultato è che la maggior parte di quelle chiamate metodo può essere "compilato out" e hanno quasi zero costi di esecuzione. Perl 6 colonne sonore centinaia o migliaia di volte più veloce su molti punti di riferimento di quello che ha fatto nel 2010, e in alcuni casi è più veloce di Perl 5.

Nel caso del problema somma da 100.000 che la questione è iniziato con, Rakudo 2018,06 è ancora un po 'più lento rispetto 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

Ma se ammortizzare il costo di avvio eseguendo il codice di 10.000 volte, vediamo una storia diversa:

$ 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 utilizza a poche centinaia di millisecondi più di perl5 all'avvio e la compilazione, ma poi capisce come fare la somma effettiva di circa 70 volte più veloce.

Altri suggerimenti

Ci sono davvero diversi motivi per cui Rakudo è così lento.

Il primo e forse più importante motivo è che Rakudo non fa ancora ottimizzazioni. Gli obiettivi attuali sono più esplorano nuove caratteristiche, e per diventare più robusto. Sai, si dice "prima farlo funzionare, allora ne fanno a destra, poi fare in fretta".

La seconda ragione è che il pappagallo non offre alcuna compilazione JIT ancora, e il garbage collector non è il più veloce. Ci sono piani per un compilatore JIT, e le persone stanno lavorando su di esso (il precedente è stato strappato fuori perché era i386 solo e un incubo di manutenzione). Ci sono anche i pensieri di porting Rakudo per altre macchine virtuali, ma che sarà sicuramente aspettare fino dopo la fine del mese di luglio.

Alla fine, nessuno può veramente dire quanto velocemente una, ben ottimizzato completa implementazione Perl 6 sarà fino a quando abbiamo una, ma mi aspetto che sia molto meglio di adesso.

A proposito del caso citato [+] 1..$big_number potrebbe essere fatto per l'esecuzione in O (1), in quanto i rendimenti 1..$big_number un intervallo, che è introspectable. Così si può utilizzare una formula somma per il caso [+] Range. Anche in questo caso si tratta di qualcosa che potrebbe essere fatto, ma che non è stato ancora fatto.

Non è certo perché Tutto è un oggetto , perché questo è vero in un certo numero di altre lingue troppo (come Ruby). Non c'è alcun motivo per cui Perl 6 dovrebbe essere magnitudini più lento di altri linguaggi come Perl 5 o Ruby, ma il fatto è che Rakudo non è così maturo come Perl o CRuby. Non c'è stata ancora l'ottimizzazione della velocità molto.

Considerando che ora la tua test è ottimizzato per un O (1) algoritmo che i rendimenti quasi istantaneamente, e che sembra quasi come ci sono diverse ottimizzazioni alla settimana;
Mi aspetto piuttosto un miglioramento delle prestazioni in tutto.

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

Anche se questo non è stato speciale carter per le gamme è ancora un po 'più veloce di quanto non fosse.
Ora fa il calcolo di prova in meno di un quinto di secondo.

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

ho presentato questi per di Fefe lingua concorrenza nel dicembre 2008. wp.pugs.pl è una traduzione letterale del Perl 5 esempio, wp.rakudo.pl è molto più sixier. Ho due programmi perché i due attuare un diverso sottoinsieme delle specifiche. informazioni di build è obsoleto nel frattempo. Le fonti:

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

Questi sono stati i risultati del 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

Oggi:

$ 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

integrazioni tardivi: Il crollo è stato affrontato a Perché ricevo 'dividere per zero` errori quando si tenta di eseguire il mio script con Rakudo ? . Il programma Rakudo è inefficiente, vedi sotto e http://justrakudoit.wordpress.com/2010/06/30/rakudo-and-speed/ .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top