2010-07-23 3 views
6

Was aus dem Dolmetscher POV, der Unterschied ist zwischen den folgenden folgenden Programmen:Perl: Warum ist es langsamer, (meine) Variablen innerhalb einer Schleife zu deklarieren?

#!/usr/bin/perl -w 

use strict; 

for (1..10000000) { 
    my $jimmy = $_**2; 
} 

und

#!/usr/bin/perl -w 

use strict; 

my $jimmy; 
for (1..10000000) { 
    $jimmy = $_**2; 
} 

"Zeit" Berichte für das erste Programm:

real 0m1.519s 
user 0m1.513s 
sys  0m0.004s 

und für die Sekunde:

real 0m1.023s 
user 0m1.012s 
sys  0m0.002s 
+2

Zusätzlich zu Robert Greiner's Antworten sind die zwei Platzierungen von 'my' in Ihrem Code semantisch unterschiedlich, was in Nicht-Spielzeug-Programmen von Bedeutung sein könnte. – msw

+4

Denken Sie daran, nur weil Sie ein Stück Code optimieren können, bedeutet das nicht, dass Sie sollten. Profilieren Sie die gesamte Anwendung und prüfen Sie, ob der Code, den Sie optimieren möchten, einen großen Teil Ihrer Verarbeitungszeit ausmacht. Versuchen Sie auch, globale und lokale Leistungsziele festzulegen, und nachdem Sie sie getroffen haben, beenden Sie die Optimierung :) –

+3

Wenn Sie eine Auflistung der zusätzlichen Operationen anzeigen möchten, die auftreten, wenn 'my' in der Schleife deklariert ist, können Sie jede davon ausführen die Skripte wie folgt und vergleichen die verschiedenen Ausgaben: 'perl -MO = Concise, -exec script.pl'. – FMc

Antwort

10

Die my Deklaration in Perl hat zwei primäre Effekte; eine Kompilierungszeit (wobei sie einen Schlitz auf dem Notizblock des enthaltenden Unterabschnitts zuordnet und sicherstellt, dass alle Verweise auf diesen Namen innerhalb des richtigen Bereichs in diesen bestimmten Zwischenspeicherplatz aufgelöst werden) und eine Laufzeitumgebung (wobei der Wert von zurückgesetzt wird) dieser Pad-Slot zu undef, oder zu einem bestimmten Wert, wenn Sie my $var = foo geschrieben haben).

Der Anteil der Kompilierungszeit hat natürlich keine amortisierten Laufzeitkosten, aber der Laufzeitabschnitt wird einmal jedes Mal ausgeführt, wenn die Ausführung die My-Deklaration passiert. Wie andere darauf hingewiesen haben, haben Ihre beiden Beispiele eine unterschiedliche Leistung, weil sie verschiedene Semantiken haben im Allgemeinen - man löscht die Variable jedes Mal durch die Schleife, und die andere nicht.

2

Die erste Schleife versucht, die Variablendeklaration für jede Iteration der Schleife zu erstellen und kann zu unnötiger Verarbeitungszeit führen.

Zugegeben, es ist nicht viel, aber dieses Zeug kann sich im Laufe der Zeit summieren, und es ist technisch langsamer, da mehr Befehle pro Iteration ausgeführt werden.

+2

Der Nachteil ist, dass Sie mehr Isolation (wenn Sie brauchte es), es innerhalb der Schleife zu deklarieren. Und es geht irgendwie mit dem Prinzipal, dass Variablen deklariert werden sollten auf den kleinsten Bereich, der Sinn macht. Natürlich, wenn Sie etwas 10 Millionen Mal anrufen, ist sklavische Hingabe an den Standard nicht erforderlich. – Axeman

+0

Ich denke, ich bin verwirrt, weil ich dachte, der Interpreter Speicher zugewiesen für jede Variable vor der Ausführung? – flies

+0

Ich denke, was ich frage ist, was Arbeit der Compiler macht, um die Variablendeklaration zu machen – flies

1

Nun, es gibt das Problem, dass Sie mit jeder Iteration eine neue Variable deklarieren.

Zwei, gibt es das größere Problem des Scoping.

Versuchen das Hinzufügen dieser Zeile nach dem for in jeder von denen, und sehen, was passiert:

print $jimmy; 

Und versuchen dies auch:

my $jimmy; 
for (1..10000000) { 
    my $jimmy = $_**2; 
} 
print $jimmy; 

Etwas ausführlicher:

A meine deklariert die aufgelisteten Variablen zu lokal (lexikalisch) zu der umschließenden Block, Datei oder Eval. Wenn mehr als ein Wert aufgeführt ist, muss die Liste in Klammern gesetzt werden.

http://perldoc.perl.org/functions/my.html

Sie werden dies wahrscheinlich finden eine nützliche lesen als auch sein:

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my%28%29

3

Da die Beispielprogramme, die Sie angegeben haben, nichts wirklich tun, ist es schwierig, Ihnen einen bestimmten Grund zu geben, warum eine Art der Deklaration besser ist als die andere. Wie viele andere Poster darauf hingewiesen haben, erzeugt die Deklaration der Variablen in der Schleife jedes Mal eine neue Variable. In Ihren Beispielen ist diese Erstellung redundant. Beachten Sie jedoch die folgenden Beispiele, die Closures verwenden.

my @closures; 
my $jimmy; 

for (1 .. 10) { 
    $jimmy = $_** 2; 
    push @closures, sub {print "$jimmy\n"}; 
} 

und diese:

my @closures; 

for (1 .. 10) { 
    my $jimmy = $_** 2; 
    push @closures, sub {print "$jimmy\n"}; 
} 

In jedem Fall wird der Code erstellt eine Reihe von Codereferenzen, aber im ersten Beispiel, da alle Code Refs beziehen sich auf den gleichen $jimmy jedem drucken 100 wenn angerufen. Im zweiten Beispiel wird jeder Code Ref eine andere Nummer (1, 4, 9, 16, 25, ...)

drucken So ist in diesem Fall der Zeitunterschied nicht wirklich wichtig, da die beiden Blöcke von Code sehr tun verschiedene Dinge.

0
  1. Deklarieren my außerhalb der Schleife bewirkt, daß die Erklärung einmal auftritt. Während der Deklaration reserviert das Perl Speicher für diese Variable.

  2. Das Deklarieren von my innerhalb der Schleife bewirkt, dass die Deklaration in jedem Intervall der Schleife erfolgt.

my Antwort Perl ist eine Variable lokal zu deklarieren - local für etwas anderes verwendet wurde und nicht bedeutet nicht das Gleiche wie das, was es in C bedeuten würde, wenn Sie die Variable innerhalb der Schleife deklarieren, wird erklärt, im lokalen Bereich zum Schleifenblock, wobei der Block in jedem Intervall beginnt/endet. Die Variable wird nicht nur deklariert, sondern sie kann auch am Ende des Blocks bereinigt (dereferenziert und/oder auf undef gesetzt) ​​werden (dies ändert sich jedoch von den Perl-Versionen).

Variablen, die außerhalb des Schleifenblocks deklariert sind, werden als "global" betrachtet (nicht wörtlich, sondern im Sinne des Schleifenblocks). Diese Variablen verwenden ihre Speicherorte erneut, anstatt nach neuen Adressen suchen zu müssen.

Verwandte Themen