Skripte ausführen
Der Befehl pperl von PetaPerl führt Perl-Skripte mit einer vertrauten Schnittstelle aus. Die meisten perl5-Optionen funktionieren identisch.
Grundlegende Ausführung
# Skript ausführen
pperl script.pl
# Mit Argumenten ausführen
pperl script.pl arg1 arg2
# Einzeiler ausführen
pperl -e 'say "Hello, World!"'
# Nur Syntax prüfen, ohne auszuführen
pperl -c script.pl
Kommandozeilenoptionen
Perl-kompatible Optionen
| Option | Beschreibung | Beispiel |
|---|---|---|
-e 'code' | Einzeiler ausführen (moderne Features immer aktiv) | pperl -e 'say "hi"' |
-c | Nur Syntax prüfen | pperl -c script.pl |
-w | Warnungen aktivieren | pperl -w script.pl |
-v | Version anzeigen | pperl -v |
-V | Ausführliche Konfiguration | pperl -V |
-h, -?, --help | Hilfe anzeigen | pperl --help |
Kombinierte Kurzoptionen:
pperl -wc script.pl # Warnungen aktivieren + Syntaxprüfung
PetaPerl-spezifische Optionen
| Option | Beschreibung | Standard |
|---|---|---|
--stats, -s | Leistungsstatistiken anzeigen (Zeit, Speicher, Ops) | Deaktiviert |
--trace, -t | Ausführungsverfolgung aktivieren | Deaktiviert |
--timeout=SECS | Zeitlimit für Ausführung in Sekunden | Keines |
--p5 | P5-Laufzeit verwenden (siehe unten) | Deaktiviert |
Auswahl der Laufzeitumgebung
PetaPerl verfügt über zwei Laufzeitumgebungen. Die standardmäßige PP-Laufzeit verwendet sicheres, idiomatisches Rust und unterstützt JIT-Kompilierung sowie Auto-Parallelisierung. Die P5-Laufzeit (--p5) ist eine zeilengetreue Rust-Übertragung des C-Interpreters von perl5 — sie erreicht unmittelbar perl5-Leistung, unterstützt aber weder JIT noch Parallelisierung.
--p5 eignet sich, wenn maximale Kompatibilität mit dem Randverhalten von perl5 oder Basisleistung ohne JIT benötigt wird. Die Standard-PP-Laufzeit (mit aktiviertem JIT) eignet sich für rechenintensive Aufgaben, bei denen Parallelisierung und JIT deutliche Geschwindigkeitsvorteile bringen.
Leistungsoptionen
| Option | Beschreibung | Standard |
|---|---|---|
--no-jit | JIT-Kompilierung deaktivieren | JIT aktiviert |
--no-parallel | Auto-Parallelisierung deaktivieren | Parallelisierung aktiv |
--threads=N | Anzahl der Threads für Parallelisierung | Alle CPUs |
--parallel-threshold=N | Minimale Iterationen für Parallelisierung | 100 |
Caching- und Analyseoptionen
| Option | Beschreibung |
|---|---|
--cache | Bytecode-Caching aktivieren (~/.pperl/cache/) |
--flush | Alle Bytecode-Caches leeren und beenden |
--dump-optree | Kanonischen Op-Tree ausgeben (nicht ausführen) |
--from-json, -j | Op-Tree von stdin lesen (B::PetaPerl-JSON-Format) |
--optree, -o | Op-Tree von stdin lesen (B::Concise-Format) |
--compare-bytecode | Op-Trees vergleichen: perl5-Backend vs. nativer Parser |
Nicht unterstützte perl5-Optionen
Folgende perl5-Flags sind nicht implementiert:
| Option | Beschreibung | Umgehung |
|---|---|---|
-I | Include-Pfad hinzufügen | PERL5LIB verwenden |
-E | Mit Features ausführen | -e verwenden (Features immer aktiv) |
-M / -m | Modul laden | use im Code verwenden |
-n / -p | Implizite Eingabeschleife | Explizite Schleife schreiben |
-l | Automatisches Zeilenende | chomp/say verwenden |
-a / -F | Autosplit | split explizit verwenden |
-i | In-Place-Bearbeitung | open/close verwenden |
-d | Debugger | - |
-x | Skript extrahieren | - |
-T | Taint-Modus | - |
Beispiele
Einzeiler
Moderne Features (say, state usw.) sind immer aktiviert.
# Hallo ausgeben
pperl -e 'say "Hello!"'
# Eingabe verarbeiten
echo "hello" | pperl -e 'while (<>) { say uc($_) }'
# Rechnen
pperl -e 'say 2 + 2'
# Daten erzeugen
pperl -e 'say join ",", 1..10'
Syntaxprüfung
# Einzelne Datei prüfen
pperl -c script.pl
# Ausgabe: script.pl syntax OK
# Mit aktivierten Warnungen prüfen
pperl -wc script.pl
Skript-Argumente
Argumente nach dem Skriptnamen befüllen @ARGV.
pperl process.pl file1.txt file2.txt
# process.pl
for my $file (@ARGV) {
say "Processing: $file";
}
Leistungsstatistiken
pperl --stats script.pl
Ausgabe:
--- Performance Statistics ---
Wall-clock time: 0.042 seconds
Peak memory (RSS): 12.34 MB (12640 KB)
Ops executed: 1523 (36261 ops/sec)
------------------------------
Ausführungsverfolgung
Jede ausgeführte Op wird angezeigt (Hilfsmittel zur Fehlersuche).
pperl --trace script.pl
Ausgabe:
[TRACE] NextState
[TRACE] Const("Hello")
[TRACE] Print
Parser-Vergleich
Ausgabe des nativen Rust-Parsers mit einem von perl5 erzeugten JSON-Op-Tree vergleichen (Analysewerkzeug).
pperl --compare-bytecode script.pl
Zeigt Unterschiede in den erzeugten Op-Trees. Nützlich zur Parser-Validierung.
Op-Tree-Inspektion
Kanonische Op-Tree-Darstellung ausgeben, ohne auszuführen.
pperl --dump-optree script.pl
Zeigt die interne Op-Tree-Struktur:
NextState(file="script.pl", line=1)
→ Const(sv="Hello")
→ Print
→ LeaveSub
Ausführungsmodell
Parser-Pipeline
Quellcode → Lexer → Parser → AST → Codegen → OpArena → Interpreter
Schnell, reines Rust. Keine perl5-Abhängigkeit zur Laufzeit.
JSON-Op-Tree-Laden (nur Analyse)
Quellcode → perl + B::PetaPerl → JSON → OpArena → Interpreter
Für Analyse und Parser-Validierung kann pperl einen von perl5 erzeugten Op-Tree über --from-json laden oder ihn über --compare-bytecode mit dem nativen Parser vergleichen. Dies wird bei normaler Ausführung nicht verwendet.
Zeitlimits
Standardmäßig hat pperl kein Zeitlimit. Mit --timeout=SECS kann eines gesetzt werden:
# Kein Zeitlimit (Standard)
pperl script.pl
# Zeitlimit setzen (nützlich für nicht vertrauenswürdigen Code oder Tests)
pperl --timeout=60 script.pl
pperl --timeout=5 script.pl
Das Test-Harness setzt ein eigenes Zeitlimit (standardmäßig 5 Sekunden pro Test). Dieses ist unabhängig vom --timeout-Flag.
Exit-Codes
| Code | Bedeutung |
|---|---|
| 0 | Erfolg |
| 1 | Laufzeitfehler oder Kompilierfehler |
| 2 | Fehler bei Kommandozeilenverwendung |
Umgebungsvariablen
| Variable | Wirkung | Standard |
|---|---|---|
PPERL_MAX_RECURSION | Maximale Rekursionstiefe für Subroutinen | 1000 |
PPERL_CACHE | Verzeichnis für Bytecode-Cache | - |
PERL5LIB | Modul-Suchpfad | - |
Beispiel:
export PPERL_MAX_RECURSION=5000
pperl deeply_recursive.pl
export PPERL_CACHE=/tmp/pperl-cache
pperl --cache script.pl
Warnungen
Warnungen mit -w oder -W aktivieren:
pperl -w script.pl
Warnungen erscheinen auf stderr. Derzeit implementiert:
- Verwendung eines nicht initialisierten Werts
- Aufruf einer undefinierten Subroutine
Standardströme
# stdin lesen
while (my $line = <STDIN>) {
print "Got: $line";
}
# stdout schreiben
print "Output\n";
say "Output with newline";
# stderr schreiben
warn "Warning message\n";
Umleitung funktioniert wie gewohnt:
pperl script.pl < input.txt > output.txt 2> errors.txt
Shebang-Unterstützung
PetaPerl-Skripte unterstützen Shebang für direkte Ausführung.
#!/usr/bin/env pperl
say "Hello from PetaPerl!";
Ausführbar machen und starten:
chmod +x script.pl
./script.pl
Modulladen
use strict;
use warnings;
use Data::Dumper;
my $data = { foo => 42 };
print Dumper($data);
Modul-Suchpfad: identisch mit perl5s @INC. Mit PERL5LIB können Verzeichnisse hinzugefügt werden.
Aktuelle Einschränkungen:
- XS-Module nicht unterstützt (nur native Module)
- Einige Pragmas (strict, warnings) werden geparst, aber nicht vollständig durchgesetzt
- Pure-Perl-Module funktionieren, sofern sie keine nicht unterstützten Features verwenden
Unterschiede zu perl5
Immer aktivierte Features
Moderne Perl-Features sind immer verfügbar (kein use feature nötig):
say- Ausgabe mit Zeilenumbruchstate- persistente lexikalische Variablen//- Defined-Or-Operator~~- Smart Match (teilweise)
Standard-Zeitlimit
pperl hat kein Standard-Zeitlimit (wie perl5). Mit --timeout=SECS kann für nicht vertrauenswürdige Skripte eines gesetzt werden.
Parser
pperl verwendet immer den nativen Rust-Parser. Es gibt keinen Laufzeit-Fallback auf perl5.
Fehlersuche
Syntaxfehler
pperl -c script.pl
Meldet Parse-Fehler mit Zeilennummern:
Parse error: Expected ';' after statement
at script.pl line 42
Laufzeitfehler
Fehler zeigen einen Stacktrace:
Runtime error: Undefined subroutine &main::foo
called at script.pl line 10
Ausführungsverfolgung
pperl --trace script.pl
Zeigt jede ausgeführte Op. Sehr ausführlich. Nützlich zum Verständnis des Ausführungsablaufs.
Leistungstipps
Benchmarking
time pperl script.pl
Oder --stats für detaillierte Metriken:
pperl --stats script.pl
Leistungscharakteristiken
Die Leistung von PetaPerl variiert je nach Arbeitslast:
- Interpreter-Fast-Paths: Häufige Operationen (Ganzzahlarithmetik, Zuweisung, Vergleich) laufen mit oder nahe perl5-Geschwindigkeit
- JIT-kompilierte Schleifen: Arithmetik-intensive Schleifen werden über Cranelift zu nativem Code kompiliert und erreichen bis zu 76-fache perl5-Geschwindigkeit
- JIT + Parallelisierung: Trivial parallelisierbare Aufgaben auf Mehrkern-Systemen erreichen bis zu 431-fache perl5-Geschwindigkeit (Mandelbrot 1000x1000)
- String-intensiver Code: Vergleichbar mit perl5 dank PvBuf-Optimierungen
- Modulladen: Ähnlich wie perl5 für Pure-Perl-Module
Mit --no-jit und --no-parallel kann die reine Interpreter-Leistung isoliert werden.
Übliche Arbeitsabläufe
Skript-Entwicklung
# Skript bearbeiten
vim script.pl
# Syntax prüfen
pperl -c script.pl
# Mit Warnungen ausführen
pperl -w script.pl
# Bei Bedarf mit Tracing debuggen
pperl --trace script.pl
Testen
# Syntax aller Skripte prüfen
find . -name '*.pl' -exec pperl -c {} \;
# Testsuite ausführen
pperl t/test.pl
Produktiv-Einsatz
# Produktionsskript ausführen (kein Zeitlimit standardmäßig)
pperl production.pl
# Leistung überwachen
pperl --stats production.pl
Fortgeschrittene Verwendung
Op-Tree aus JSON laden (Analyse)
Für Parser-Validierung und Analyse:
# JSON-Format (B::PetaPerl) — liest von stdin
perl -MO=PetaPerl script.pl | pperl --from-json
# Kurzform
perl -MO=PetaPerl script.pl | pperl -j
Dies lädt einen von perl5 erzeugten Op-Tree und führt ihn in der PetaPerl-Laufzeit aus, wobei der native Parser umgangen wird.
Parser vergleichen
Ausgabe des nativen Parsers mit einem von perl5 erzeugten Op-Tree vergleichen:
pperl --compare-bytecode script.pl
Zeigt strukturelle Unterschiede. Exit-Code 0 = äquivalent, 1 = verschieden.
Fehlerbehebung
“Can’t open perl script”
Datei existiert nicht oder falscher Pfad.
pperl script.pl # Muss existieren
“Undefined subroutine”
Subroutine nicht definiert oder im aktuellen Gültigkeitsbereich nicht sichtbar.
sub greet { say "hi" }
greet(); # OK
greeet(); # Fehler: Undefined subroutine
“Timeout expired”
Das Skript lief länger als der --timeout-Wert.
pperl --timeout=120 long_script.pl # Zeitlimit erhöhen
pperl long_script.pl # Kein Zeitlimit (Standard)
“Parse error”
Syntaxfehler im Skript. Mit -c prüfen:
pperl -c script.pl
“Is perl installed and in PATH?”
Die Analysewerkzeuge --from-json/-j und --compare-bytecode erfordern ein installiertes perl 5.42+ mit B::PetaPerl. Normale Ausführung benötigt kein perl.
Versionsinformationen
pperl -v
Zeigt Kurzversion und Copyright.
pperl -V
Zeigt ausführliche Konfiguration:
Summary of PetaPerl configuration:
PetaPerl:
version='0.1.0'
binary='pperl'
Runtime:
backend=Rust interpreter + function-pointer dispatch
jit=Cranelift (for/while loops)
parallelism=Rayon (auto-parallel map/grep/for/while)
Perl compatibility:
parser=native Rust
perl_required=no (5.42+ optional for --from-json/--compare-bytecode analysis)
platforms=Linux only
Plattform-Unterstützung
PetaPerl läuft ausschließlich unter Linux (jede Architektur).
Nicht unterstützt: Windows, macOS, BSD, VMS usw.
Diese Vereinfachung ermöglicht aggressive Optimierung für Linux-spezifische Funktionen.
Geplante Erweiterungen
Geplante Features:
- Profiling-Ausgabe (
--profile) - Erweiterte JIT-Abdeckung (String-Operationen, Subroutine-Inlining)
- Erweiterte Parallelisierung (weitere Schleifenmuster, Pipeline-Parallelismus)
Fortschritt verfolgen: https://gl.petatech.eu/petatech/peta-perl