GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie begrenzen Pipelines die Speichernutzung?

Brian Kernighan erklärt in diesem Video die frühe Attraktivität der Bell Labs für kleine Sprachen/Programme, die auf Speicherbeschränkungen basieren

Eine große Maschine hätte 64 kByte – K, nicht M oder G – und das bedeutete, dass jedes einzelne Programm nicht sehr groß sein konnte, und so gab es eine natürliche Tendenz, kleine Programme zu schreiben, und dann der Pipe-Mechanismus, im Grunde genommen Eingaben Ausgabeumleitung, ermöglichte es, ein Programm mit einem anderen zu verknüpfen.

Aber ich verstehe nicht, wie dies die Speichernutzung einschränken könnte, wenn man bedenkt, dass die Daten im RAM gespeichert werden müssen, um zwischen Programmen übertragen zu werden.

Aus Wikipedia:

In den meisten Unix-ähnlichen Systemen werden alle Prozesse einer Pipeline gleichzeitig gestartet [Hervorhebung von mir] , deren Streams entsprechend verbunden und vom Scheduler zusammen mit allen anderen Prozessen verwaltet werden, die auf dem Computer ausgeführt werden. Ein wichtiger Aspekt, der Unix-Pipes von anderen Pipe-Implementierungen unterscheidet, ist das Konzept der Pufferung:Beispielsweise kann ein sendendes Programm 5000 Bytes pro Sekunde produzieren, und ein empfangendes Programm kann möglicherweise nur 100 Bytes pro Sekunde akzeptieren, aber nein Daten gehen verloren. Stattdessen wird die Ausgabe des sendenden Programms im Puffer gehalten. Wenn das empfangende Programm bereit ist, Daten zu lesen, liest das nächste Programm in der Pipeline aus dem Puffer. Unter Linux beträgt die Größe des Puffers 65536 Bytes (64 KB). Ein Open-Source-Drittanbieterfilter namens bfr ist verfügbar, um bei Bedarf größere Puffer bereitzustellen.

Dies verwirrt mich noch mehr, da dies den Zweck kleiner Programme völlig zunichte macht (obwohl sie bis zu einem bestimmten Umfang modular sein würden).

Das einzige, was mir als Lösung für meine erste Frage einfällt (die Speicherbeschränkungen sind problematisch, abhängig von der Größe der Daten), wäre, dass große Datensätze damals einfach nicht berechnet wurden und das eigentliche Problem, das Pipelines lösen sollten, das war Menge an Speicher, die von den Programmen selbst benötigt wird. Aber angesichts des fettgedruckten Textes im Wikipedia-Zitat verwirrt mich selbst das:da nicht jeweils ein Programm implementiert wird.

All dies würde sehr viel Sinn machen, wenn temporäre Dateien verwendet würden, aber meines Wissens schreiben Pipes nicht auf die Festplatte (es sei denn, es wird Swap verwendet).

Beispiel:

sed 'simplesubstitution' file | sort | uniq > file2

Mir ist klar, dass sed liest die Datei ein und gibt sie zeilenweise aus. Aber sort , wie BK im verlinkten Video feststellt, ist ein Punkt, also müssen alle Daten in den Speicher gelesen werden (oder doch?), dann werden sie an uniq weitergegeben , was (meiner Meinung nach) ein One-Line-at-a-Time-Programm wäre. Aber zwischen der ersten und zweiten Pipe müssen alle Daten im Speicher sein, oder?

Siehe auch:Ubuntu – Ausführen eines Befehls beim Einlegen einer CD/DVD/BD?

Akzeptierte Antwort:

Die Daten müssen nicht im RAM gespeichert werden. Pipes blockieren ihre Schreiber, wenn die Leser nicht da sind oder nicht mithalten können; Unter Linux (und den meisten anderen Implementierungen, stelle ich mir vor) gibt es etwas Pufferung, aber das ist nicht erforderlich. Wie von mtraceur und JdeBP erwähnt (siehe die Antwort des letzteren), haben frühe Versionen von Unix Pipes auf die Festplatte gepuffert, und so haben sie dazu beigetragen, die Speichernutzung zu begrenzen:Eine Verarbeitungspipeline konnte in kleine Programme aufgeteilt werden, von denen jedes einige Daten verarbeiten würde , innerhalb der Grenzen der Plattenpuffer. Kleine Programme benötigen weniger Speicher, und die Verwendung von Pipes bedeutete, dass die Verarbeitung serialisiert werden konnte:Das erste Programm würde ausgeführt, seinen Ausgabepuffer füllen, angehalten, dann das zweite Programm geplant, den Puffer verarbeiten usw. Moderne Systeme sind Befehle um Größenordnungen größer als die frühen Unix-Systeme und kann viele Pipes parallel ausführen; aber bei großen Datenmengen sieht man immer noch einen ähnlichen Effekt (und Varianten dieser Art von Technik werden für die Verarbeitung von „Big Data“ verwendet).

In Ihrem Beispiel

sed 'simplesubstitution' file | sort | uniq > file2

sed liest Daten aus file ggf. schreibt es dann so lange wie sort ist bereit, es zu lesen; wenn sort nicht bereit ist, blockiert das Schreiben. Die Daten leben tatsächlich irgendwann im Speicher, aber das ist spezifisch für sort , und sort ist bereit, sich mit allen Problemen zu befassen (es werden temporäre Dateien verwendet, wenn die zu sortierende Datenmenge zu groß ist).

Sie können das Blockierungsverhalten sehen, indem Sie

ausführen
strace seq 1000000 -1 1 | (sleep 120; sort -n)

Dies erzeugt eine beträchtliche Menge an Daten und leitet sie an einen Prozess weiter, der nicht bereit ist, irgendetwas zu lesen für die ersten zwei Minuten. Sie sehen eine Reihe von write Operationen durchlaufen, aber sehr schnell seq wird anhalten und warten, bis die zwei Minuten abgelaufen sind, die vom Kernel blockiert werden (das write Systemaufruf wartet).


Linux
  1. Linux-Speichernutzung

  2. Linux – Speichernutzung für einen einzelnen Linux-Prozess begrenzen?

  3. So ermitteln Sie die Benutzerspeichernutzung in Linux

  4. Begrenzen Sie die Speichernutzung für einen einzelnen Linux-Prozess

  5. Wie kann die ClamAV-Speichernutzung reduziert werden?

So überprüfen Sie die Speichernutzung in Linux

So überprüfen Sie die Speichernutzung in Debian 10

So finden Sie die am häufigsten ausgeführten Prozesse nach Speichernutzung

Wie wird die Top/htop-Speichernutzung interpretiert?

So sortieren Sie den obersten Befehl basierend auf der Speichernutzung

Wie kann ich die Speichernutzung profilieren?