Hier geht es nicht um das Öffnen einer Datei im Vergleich zu einer Variablen Inhalt zu lesen , sondern mehr über einen zusätzlichen Prozess Forking oder nicht.
grep -oP '^MemFree: *\K[0-9]+' /proc/meminfo
Forks Ein Prozess, der ausgeführt wird und grep
geöffnet wird /proc/meminfo
(eine virtuelle Datei im Arbeitsspeicher, ohne dass Festplatten-E / A betroffen sind), liest sie und stimmt mit dem regulären Ausdruck überein.
Der teuerste Teil dabei ist, den Prozess zu forken und das grep-Dienstprogramm und seine Bibliotheksabhängigkeiten zu laden, die dynamische Verknüpfung durchzuführen, die Gebietsschemadatenbank zu öffnen und Dutzende von Dateien auf der Festplatte (aber wahrscheinlich im Arbeitsspeicher zwischengespeichert).
Der Teil über das Lesen /proc/meminfo
ist im Vergleich unbedeutend, der Kernel benötigt wenig Zeit, um die darin enthaltenen Informationen zu generieren, und grep
benötigt wenig Zeit, um sie zu lesen.
Wenn Sie strace -c
damit arbeiten, werden Sie feststellen, dass der eine open()
und der andere read()
Systemaufruf, der zum Lesen verwendet /proc/meminfo
wird, Erdnüsse ist, im Vergleich zu allem, was grep
zum Starten strace -c
erforderlich ist ( ohne Gabelung).
Im:
a=$(</proc/meminfo)
In den meisten Shells, die diesen $(<...)
ksh-Operator unterstützen, öffnet die Shell nur die Datei und liest ihren Inhalt (und entfernt die nachfolgenden Zeilenumbrüche). bash
ist anders und viel weniger effizient, da es einen Prozess zum Lesen auffordert und die Daten über eine Pipe an das übergeordnete Element weiterleitet. Aber hier ist es einmal gemacht, also spielt es keine Rolle.
Im:
printf '%s\n' "$a" | grep '^MemFree'
Die Shell muss zwei Prozesse erzeugen , die gleichzeitig ablaufen, aber über eine Pipe miteinander interagieren. Das Erstellen, Abreißen und Schreiben und Lesen von Pfeifen ist mit geringen Kosten verbunden. Die weitaus höheren Kosten entstehen durch einen zusätzlichen Prozess. Die Planung der Prozesse hat ebenfalls einen Einfluss.
Möglicherweise können Sie feststellen, dass die Verwendung des <<<
Operators zsh den Vorgang etwas beschleunigt:
grep '^MemFree' <<< "$a"
In zsh und bash geschieht dies durch Schreiben des Inhalts $a
in eine temporäre Datei. Dies ist kostengünstiger als das Erstellen eines zusätzlichen Prozesses, bietet jedoch wahrscheinlich keinen Gewinn im Vergleich zum direkten Abrufen der Daten /proc/meminfo
. Das ist immer noch weniger effizient als Ihr Ansatz, der /proc/meminfo
auf die Festplatte kopiert , da das Schreiben der temporären Datei bei jeder Iteration erfolgt.
dash
Unterstützt keine Here-Strings, aber seine Heredocs werden mit einer Pipe implementiert, die keinen zusätzlichen Prozess beinhaltet. Im:
grep '^MemFree' << EOF
$a
EOF
Die Shell erzeugt eine Pipe, gabelt einen Prozess. Das untergeordnete Element wird grep
mit der Standardeingabe als Leseende der Pipe ausgeführt, und das übergeordnete Element schreibt den Inhalt am anderen Ende der Pipe.
Das Pipehandling und die Prozesssynchronisation sind jedoch wahrscheinlich immer noch teurer, als nur die Daten direkt abzurufen /proc/meminfo
.
Der Inhalt von /proc/meminfo
ist kurz und braucht nicht viel Zeit, um zu produzieren. Wenn Sie einige CPU-Zyklen einsparen möchten, möchten Sie die teuren Teile entfernen: Prozesse forken und externe Befehle ausführen.
Mögen:
IFS= read -rd '' meminfo < /proc/meminfo
memfree=${meminfo#*MemFree:}
memfree=${memfree%%$'\n'*}
memfree=${memfree#"${memfree%%[! ]*}"}
Vermeiden Sie bash
jedoch, dass die Musterübereinstimmung sehr unzureichend ist. Mit zsh -o extendedglob
können Sie es verkürzen auf:
memfree=${${"$(</proc/meminfo)"##*MemFree: #}%%$'\n'*}
Beachten Sie, dass dies ^
in vielen Shells besonders ist (Bourne, fish, rc, es und zsh mindestens mit der Option extendedglob). Ich würde empfehlen, es zu zitieren. Beachten Sie auch, dass echo
nicht zur Ausgabe beliebiger Daten verwendet werden kann (daher meine Verwendung von printf
oben).