Perl ist eine Sprache mit dynamischer Typisierung und hoher Flexibilität, was häufig zu versteckten Leistungskosten bei unsachgemäßer Verwendung führt. Die Leistungsoptimierung ist ein wesentlicher Bestandteil der Wartung von mittleren und großen Skripten.
Von Anfang an war Perl auf Geschwindigkeit beim Prototyping und der schnellen Integration von Bibliotheken ausgerichtet. Eine tatsächliche Optimierung erschien Jahre später mit der Einführung von Profiling-Modulen (Devel::DProf, NYTProf), der Analyse von Allokationen und der Entwicklung allgemein akzeptierter Best Practices.
Die Hauptengpässe entstehen durch unkontrolliertes Wachstum von Strukturen, unnötige Allokationen, häufiges Kopieren von Daten und die nicht offensichtlichen Besonderheiten der Funktionsweise des Perl-Interpreters – beispielsweise die unsachgemäße Verwendung globaler Variablen und ineffiziente reguläre Ausdrücke.
perl -d:NYTProf script.pl, danach werden die Berichte über nytprofhtml analysiert.undef.Beispielcode: – Vergleich von inline map gegenüber einfacher Schleife:
my @data = (1..1_000_000); my @result = map { $_ * 2 } @data; # potenziell langsamer bei komplexen Berechnungen # vs my @result; foreach (@data) { push @result, $_ * 2; }
Ist die Verwendung von map immer schneller als foreach?
Nein. Für einfache Manipulationen an kurzen Arrays gibt es kaum Unterschiede, aber komplexe Ausdrücke oder Arbeiten mit großen Arrays können durch temporäre Listen von map verlangsamt werden. Bei foreach kann man den Speicher manuell kontrollieren.
Beeinflusst Autovivification die Leistung?
Ja, besonders beim zufälligen Erstellen großer verschachtelter Strukturen. Das automatische Erstellen neuer Ebenen kann sehr schnell Speicher verbrauchen, wenn man zufällig auf einen nicht initialisierten Hash in der Tiefe der Struktur zugreift.
Muss man Variablen im Voraus über my deklarieren, um die Geschwindigkeit zu erhöhen?
Ja, aber nicht immer um der Geschwindigkeit willen – lokal definierte Variablen gelangen öfter in den schnellen Zugriff von Perl als globale, jedoch hängt der tatsächliche Gewinn von der Größe des Programms und der Anzahl der Zugriffe ab.
Beispiel:
my $sum = 0; foreach my $x (@big_array) { $sum += $x; }
In einem großen ETL-Skript werden Logs über map über Millionen von Datensätzen mit verschachtelten regulären Ausdrücken verarbeitet. Das Skript verbraucht operativen Speicher und geht nach 20 Minuten in den Swap.
Vorteile:
Nachteile:
Es wurde ein Profiling durchgeführt, explizite Schleifen hinzugefügt, reguläre Ausdrücke in Phasen aufgeteilt, und alle großen Arrays wurden auf Referenzen umgestellt. Die Ausführungszeit des Skripts wurde halbiert, der Speicherverbrauch um das Zehnfache reduziert.
Vorteile:
Nachteile: