Verlangsamt das T-Stück Pipelines?

10

Ich frage mich, ob Tee die Pipelines verlangsamt. Das Schreiben von Daten auf die Festplatte ist schließlich langsamer als das Weiterleiten.

Wartet tee mit dem Senden von Daten an die nächste Pipe, bis sie auf die Festplatte geschrieben wurden? (Wenn nicht, muss tee wohl Daten in die Warteschlange stellen, die mitgesendet, aber nicht auf die Festplatte geschrieben wurden, was für mich unwahrscheinlich klingt.)

$ program1 input.txt | tee intermediate-file.txt | program2 ...
Die Unfun Cat
quelle
Nein, diese "nächste Pfeife" ist das allererste, an das sie schreibt (auch hier erwähnt ).
ManRow

Antworten:

12

Ja, es verlangsamt die Dinge. Und es hat im Grunde eine Warteschlange mit ungeschriebenen Daten, obwohl diese tatsächlich vom Kernel verwaltet wird - alle Programme haben diese, sofern sie nicht ausdrücklich etwas anderes anfordern.

Hier ist zum Beispiel eine triviale Pipe mit pv, was schön ist, weil es die Übertragungsrate anzeigt:

$ pv -s 50g -S -pteba /dev/zero | cat > /dev/null 
  50GiB 0:00:09 [ 5.4GiB/s] [===============================================>] 100%

Fügen wir nun eine hinzu und teeschreiben nicht einmal eine zusätzliche Kopie - leiten Sie sie einfach weiter:

$ pv -s 50g -S -pteba /dev/zero | tee | cat > /dev/null 
  50GiB 0:00:20 [2.44GiB/s] [===============================================>] 100%            

Das ist also etwas langsamer und es hat nicht einmal etwas getan! Das ist der Aufwand für das interne Kopieren von STDIN nach STDOUT. (Interessanterweise pvbleibt das Hinzufügen einer Sekunde dort bei 5,19 GB / s, pvist also wesentlich schneller als tee. pvVerwendet splice(2), teewahrscheinlich nicht.)

Wie auch immer, mal sehen, was passiert, wenn ich sage tee, dass ich in eine Datei auf der Festplatte schreiben soll. Es beginnt ziemlich schnell (~ 800 MB / s), verlangsamt sich jedoch im Laufe der Zeit immer weiter - letztendlich auf ~ 100 MB / s, was im Grunde 100% der Festplattenschreibbandbreite entspricht. (Der schnelle Start ist darauf zurückzuführen, dass der Kernel das Schreiben der Festplatte zwischenspeichert, und die Verlangsamung der Schreibgeschwindigkeit der Festplatte ist der Kernel, der sich weigert, den Cache unendlich wachsen zu lassen.)

Ist das wichtig?

Das Obige ist ein Worst-Case. Das obige verwendet eine Pipe, um Daten so schnell wie möglich auszuspucken. Die einzige reale Verwendung, die ich mir so vorstellen kann, ist das Weiterleiten von YUV-Rohdaten an / von ffmpeg.

Wenn Sie Daten mit langsameren Raten senden (weil Sie sie verarbeiten usw.), ist dies ein viel weniger bedeutender Effekt.

derobert
quelle
Schöne
Erklärung
5

Immerhin hier nichts Überraschendes

> POSIX sagt :

BESCHREIBUNG

Das Tee- Dienstprogramm kopiert die Standardeingabe in die Standardausgabe und erstellt eine Kopie in null oder mehr Dateien. Das Tee- Dienstprogramm darf die Ausgabe nicht puffern.

Und auch das

RATIONALE

Die Pufferanforderung bedeutet, dass Tee keine vollständig gepufferten oder zeilengepufferten Schreibvorgänge nach ISO C-Standard verwenden darf. Dies bedeutet nicht, dass Tee 1-Byte-Lesevorgänge gefolgt von 1-Byte-Schreibvorgängen ausführen muss.

Ohne "Begründung" zu erklären, teewird wahrscheinlich nur gelesen und geschrieben, wie viele Bytes gleichzeitig in Ihren Pipe-Puffer passen, wodurch die Ausgabe bei jedem einzelnen Schreibvorgang geleert wird.

Und ja, je nach Anwendung kann dies ziemlich ineffizient sein. Sie können diese einfach entfernen / kommentieren:
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L208
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L224

ManRow
quelle
+1 für die Links zum verantwortlichen Quellcode. Sind diese Teile wirklich alles, was für dieses Verhalten verantwortlich ist, sodass das Entfernen / Auskommentieren sie teeschneller laufen lässt?
Hashim
1
Sieht so aus, als wäre das der Fall! Tee überschreibt das Pufferschema, das ansonsten vom Betriebssystem ausgewählt wurde
ManRow