2010-12-28 9 views
2

Ich schreibe gerade ein Skript, das eine Datenbank als Eingabe nimmt und alle gültigen Kombinationen aus den über 10 Tabellen nach bestimmten Regeln generiert. Da der Ausgang verflixt ist riesig, ich Dumping i dies durch gzip in die Datei, wie folgt aus:Wie kann ich schreiben, um eine Gzip-Datei von meinem Perl-Skript nicht blockierend?

open(my $OUT, '|-', "gzip > file"); 
for (@data) { 
    my $line = calculate($_); 
    print $OUT $line; 
} 

Aufgrund der Natur des Tieres, obwohl ich am Ende zu Hunderttausenden von kleinen schreibt zu machen, eine für jede Zeile. Das bedeutet, dass es zwischen den Berechnungen auf gzip wartet, um die Daten zu erhalten und die Komprimierung zu beenden. Zumindest denke ich, ich könnte mich irren.

Falls ich recht habe, frage ich mich, wie ich diesen Druck asynchron machen kann, d. H. Er feuert die Daten bei gzip und fährt dann mit der Verarbeitung der Daten fort.

Antwort

2

Pipes verwenden bereits einen Puffer, damit das Schreibprogramm nicht auf das Leseprogramm warten muss. Dieser Puffer ist jedoch normalerweise ziemlich klein (unter Linux ist er normalerweise nur 64 KB groß) und kann nicht einfach geändert werden (er muss den Kernel neu kompilieren). Wenn der Standardpuffer nicht genug ist, ist die einfachste Sache zu tun, um einen Puffer Programm in der Pipeline ist:

open(my $OUT, '|-', "bfr | gzip > file"); 

bfr liest einfach STDIN in einen in-Speicherpuffer und schreibt an STDOUT so schnell wie das nächste Programm erlaubt. Der Standardwert ist ein 5 MB-Puffer, aber Sie können dies mit der Option -b ändern (z. B. bfr -b10m für einen 10 MB-Puffer).

+0

Danke dafür! Ich bin nicht in der Nähe dieses Puffers, mit einer einzigen Pipe-Pipeline für gzip, die 850 Bytes lang ist. :) – Mithaldu

1

natürlich werde ich es in einem Gewinde oder mit einer Gabel tun, wie Sie es wünschen. http://hell.jedicoder.net/?p=82

+3

"Thread" Nein. Nicht in Perl. Der Versuch, Threads in Perl zu verwenden, führt nur zu Untergang und Tränen. Fork wäre eine Option, wenn es meinen Debugger nicht brechen würde (und ich war nicht auf Windows). – Mithaldu

+1

eads zu doom und tränen: ich werde mich daran erinnern :) (ich habe es nie benutzt) – ykatchou

+0

eine andere lösung für mich (aber nicht unter windows) war etwas wie system ("gzip - $ line &"); – ykatchou

4

Gib IO::Compress::Gzip einen Versuch. Es akzeptiert eine filehandle um zu schreiben. Sie können set O_NONBLOCK auf diesem Dateihandle.

+0

Die Komprimierung in Per durchführen l ist im Grunde das genaue Gegenteil von dem, was ich will, fürchte ich. das O_NONBLOCK Ding ist jedoch interessant. Ich weiß nur nicht, ob ich es auf ein Rohr zu einem anderen Prozess anwenden kann. – Mithaldu

+0

Das letzte Mal, als ich es getestet habe, war die Verwendung von IO :: Compress :: Gzip wesentlich langsamer als das Erzeugen eines 'gzip' Prozesses. – cjm

Verwandte Themen