Ich muss einen Befehl wie den folgenden verwenden:
$ cat large.input.file | process.py > large.output.file
Das Problem ist, dass es der Festplatte nicht schwer fällt, zwischen dem Lesen der Eingabedatei und dem Schreiben der Ausgabedatei zu springen.
Gibt es eine Möglichkeit, bash anzuweisen, bei dieser Art von Pipe einen großen Speicherpuffer zu verwenden?
Das Betriebssystem puffert die Ausgabe bis zu einem bestimmten Betrag, aber es kann immer noch zu einer starken Kopfbewegung kommen, wenn sich sowohl die Eingabe- als auch die Ausgabedatei auf demselben Laufwerk befinden, es sei denn, Sie führen
process.py
eine eigene Pufferung durch.Sie können
cat
in Ihrem Beispiel den Pipe Viewer (pv) ersetzen (verfügbar in den meisten Standard-Repositorys und problemlos einzuhalten, wenn er nicht im Repo Ihrer Distribution enthalten ist), mit dem Sie festlegen können, dass mehr Puffer (mit den Optionen-B
/--buffer-bytes
) und a angezeigt werden Fortschrittsbalken (es sei denn, Sie fordern ihn nicht auf), der für einen langen Vorgang sehr praktisch sein kann, wenn Sieprocess.py
keine eigenen Fortschrittsinformationen ausgeben. Wenn Daten von einem Ort auf einem Laufwerk an einen anderen Ort auf demselben Laufwerk übergeben werden, kann dies einen großen Unterschied machen, es sei denn, der Gesamtprozess ist in erster Linie an die CPU und nicht an die E / A gebunden.Für einen 1-MB-Puffer könnten Sie also Folgendes tun:
Ich benutze die
pv
ganze Zeit für diese Art von Dingen, obwohl hauptsächlich für die Fortschrittsanzeige mehr als die einstellbare Puffergröße.Eine andere Option ist die Verwendung des "Standard" (Standard in Bezug auf die allgemeine Verfügbarkeit, das Befehlszeilenformat unterscheidet sich ein wenig von den meisten gängigen Befehlen)
dd
, obwohl dies nicht über die Fortschrittsbalkenfunktion verfügt:Bearbeiten: ps. Anhänger weisen möglicherweise darauf hin, dass
cat
dies in Ihrem Beispiel nicht erforderlich ist, da Folgendes genauso gut funktioniert und etwas effizienter ist:Einige Leute bezeichnen die Beseitigung nicht bedingter Aufrufe
cat
als "Demogifizierung", diese Leute sollten wahrscheinlich nicht ermutigt werden ...quelle
cat
zu teuer ist, sollten sie wahrscheinlich ihre Schale beheben , um automatisch zu ersetzencat _single_file_ |
mit< _single_file
. Ich werdecat _single_file_ |
stattdessen weiter schreiben .Gibt es nicht ein altes Unix-Tool namens "buffer"? Nicht, dass dies bei den heutigen Caching-Techniken erforderlich wäre - aber es ist da.
quelle
Ich glaube, dass das Problem, auf das sich der Benutzer bezieht, darin besteht, wie die Eingabe / Ausgabe im Allgemeinen in der UNIX / Linux-Welt funktioniert. Grundsätzlich kann für jeden UNIX / Linux-Prozess jeweils nur eine E / A-Operation ausstehen. Im Fall des Befehls cat im Beispiel liest der Befehl cat zuerst einige Daten, wartet auf deren Abschluss, schreibt dann die Daten und wartet auf deren Abschluss, bevor er fortfährt. Es gibt keine gleichzeitige E / A innerhalb eines Prozesses, daher wird die Pufferung nur zwischen den Lese- und Schreibvorgängen verwendet, um einfach vorübergehend einige Daten zu speichern.
Um die Arbeit zu beschleunigen, können die Eingabe und Ausgabe auf zwei verschiedene Prozesse aufgeteilt werden: einen Lese- und einen Schreibprozess sowie viel gemeinsam genutzten Speicher, der als Puffer zwischen den beiden Prozessen verwendet wird. Dies führt zu der gewünschten gleichzeitigen E / A und kann den Dateiübertragungsprozess beschleunigen.
Der von einem Benutzer angegebene Dienstprogrammpuffer implementiert diese von mir beschriebene gleichzeitige Methode. Ich habe das Pufferprogramm mit einem ziemlich großen gemeinsam genutzten Speicherpuffer verwendet, als ich eine Schnittstelle zu einem Bandlaufwerk für Sicherungen herstellte. Dies führte zu einer Verringerung der Übertragungszeit der Wanduhr um etwa 20%.
Die Verwendung des Pufferprogramms als Ersatz für den Befehl 'cat' kann zu einigen deutlichen Verbesserungen führen ... abhängig davon.
Genießen!
quelle
Versuchen Sie es mit diesem kleinen Python 2-Programm, das ich gerade zusammengestellt habe:
Um diese Datei zu verwenden, nennen Sie sie wie folgt:
Sie können 2K verwenden, um 2 Kilobyte anzugeben, 2M für 2 Megabyte, 2G für 2 Gigabyte. Wenn Sie möchten, können Sie 2T für 2 Terabyte Puffer hinzufügen: 3
Ich bekomme dieses Problem immer wieder, wenn ich ein Image einer virtuellen Maschine mit komprimiere
pigz -1
, weil dies die Komprimierung so unglaublich schnell macht, dass die Festplatte gleichzeitig zu lesen und zu schreiben beginnt und der Prozess zum Stillstand kommt, wenn der Kopf der Festplatte zwischen den Eingabe- und Ausgabedateien schwirrt . Also habe ich dieses kleine Programm erstellt, das einen gigantischen Datenblock von der Standardeingabe liest, in die Standardausgabe schreibt und wiederholt. Wenn der Lesevorgang eine leere Zeichenfolge zurückgibt, wurde keine Standardeingabe mehr empfangen und das Skript wird beendet.quelle
read()
kann mitE_AGAIN
in UNIX-ähnlichen Systemen scheitern und Ihr Programm würde dannexit()
vorzeitig. Überprüfen Sie immer explizit auf EOF.Es wird intelligent gepuffert, aber es gibt keine gute Möglichkeit, den Betrag zu optimieren.
Sie könnten ein Zwischenprogramm schreiben, das das gewünschte Caching ausführt und es von der Eingabe lesen lässt.
quelle
Ihr Betriebssystem führt alle Arten von Caching für Dateien durch, bevor diese auf die Festplatte geschrieben werden, und führt auch das Caching für die gelesene Datei durch (im Allgemeinen wenn möglich vorauslesen). Lassen Sie das Betriebssystem das Puffern und Zwischenspeichern durchführen.
Bis Sie mithilfe von Tests und Profilen nachweisen können, dass die Festplatte der begrenzende Faktor in der Gleichung ist, lassen Sie sie am besten in Ruhe.
Wenn Sie process.py ändern können, können Sie statt direkt lesen / schreiben mit Pipes lesen / schreiben und stattdessen Puffer- und / oder Memmap-Dateien verwenden, um einen Teil der Last vom System zu entfernen.
quelle