Was ist der Overhead bei der Verwendung von Subshells?

Was ist der Overhead bei der Verwendung von Subshells?

Hoffentlich ist diese Frage nicht zu allgemein. Ich bin sehr neu im Shell-Scripting und komme aus dem Bereich Computerarchitektur/nicht-Scripting-Programmierung. Mir ist bei den Skripten bei meiner Arbeit aufgefallen, dass sie selten geschrieben werden, indem man eine Unter-Shell um das gesamte Skript legt. Wenn ich die Skripte schreibe, schließe ich sie in eine Unter-Shell ein, da sie dann nicht mit anderen Skripten in Konflikt geraten, die meine aufrufen (nur für den Fall). Ist das nicht gängige Praxis, weil dieser Ansatz mit einem gewissen Mehraufwand verbunden ist? Es fällt mir schwer, dies online zu finden.

Beispiel:

#!/bin/bash
( #Start of subshell
echo "Some stuff here"
) #End of subshell

Antwort1

Subshells haben Overhead.

Auf meinem System betragen die minimalen Fork-Exec-Kosten (wenn Sie ein Programm von der Festplatte ausführen, wenn die Datei nicht kalt ist) etwa 2msund die minimalen Forking-Kosten betragen etwa 1ms.

Bei Subshells sprechen Sie nur von den Forking-Kosten, da keine Datei execbearbeitet werden muss. Wenn die Subshells einigermaßen niedrig gehalten werden, 1msist dies bei Programmen, die von Menschen bedient werden, ziemlich vernachlässigbar. Ich glaube, Menschen können nichts bemerken, was schneller passiert als 50ms(und so lange dauert es normalerweise, bis moderne Interpreter von Skriptsprachen überhaupt starten (ich spreche hier pythonvon Ruby rvm), wobei die neuesten nodejsetwa benötigen 100ms).

Bei Schleifen kommt es jedoch zu einer Aufsummierung, und dann möchten Sie vielleicht beispielsweise das recht gebräuchliche Bactick oder $()Muster ersetzen, bei dem Sie returnetwas aus einer Funktion ausgeben, indem Sie es auf stdout drucken, damit die übergeordnete Shell es durch Bashismen wie diese erfassen kann printf -v(oder ein schnelles externes Programm verwenden, um den gesamten Stapel zu verarbeiten).

DerBash-VervollständigungPaket vermeiden speziell diese Subshell-Kosten, indem sie über übergebene Variablennamen zurückkehren, mit einer Technik, die unter beschrieben wirdhttp://fvue.nl/wiki/Bash:_Passing_variables_by_reference


Vergleichen

time for((i=0;i<10000;i++)); do echo "$(echo hello)"; done >/dev/null 

mit

time for((i=0;i<10000;i++)); do echo hello; done >/dev/null 

sollte Ihnen eine gute Schätzung des Systemaufwands geben fork.

Antwort2

Das Ausführen des hervorragenden Codes von PSkocik auf meinem System zeigte vernachlässigbare Ergebnisse.

Dieses Beispiel ist jedoch wirklich treffend - native Befehle vs. Subshell-Befehle:

MyPath="path/name.ext" 
# this takes forever
time for((i=0;i<10000;i++)); do echo "$(basename ${MyPath} )"; done >/dev/null 
#this is over 100x less time 
time for((i=0;i<10000;i++)); do echo "${MyPath##*/}"; done >/dev/null     

verwandte Informationen