Was ist der Aufwand für die Verwendung von Subshells?


9

Hoffentlich ist diese Frage nicht zu allgemein. Ich bin sehr neu in Shell-Scripting und komme aus einer Computerarchitektur / Nicht-Scripting-Programmierung. Ich habe bei den Skripten bei meiner Arbeit festgestellt, dass die Skripte selten geschrieben werden, indem eine Unter-Shell um das gesamte Skript erstellt wird. In den Skripten, die ich schreibe, bin ich es, wenn ich es mit einer Sub-Shell umhüllen kann, da es verhindert, dass es mit anderen Skripten, die meine aufrufen, in Konflikt gerät (nur für den Fall). Ist dies nicht eine gängige Praxis, da mit diesem Ansatz ein gewisser Aufwand verbunden ist? Es fällt mir schwer, dies online zu finden.

Beispiel:

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

1
Wie rufen diese anderen Skripte Ihr Skript auf? Verwenden sie beispielsweise a sourceoder führen sie stattdessen Ihr Skript aus?
Thrig

1
Ausgehend von einem Programmierhintergrund gibt es auf dieser Site einen Beitrag, der eine obligatorische Einführung in das Shell-Scripting sein sollte - er behandelt die konzeptionellen Unterschiede zwischen bashund z. B. C. Die wahre Antwort auf diese "Overhead" -Frage ist wirklich eine Nichtantwort: Wenn Wenn Sie sich Sorgen über den Leistungsaufwand machen, sollten Sie kein Shell-Skript verwenden.
Wildcard

Könnten Sie bitte klarstellen, was Sie unter "einer Unterschale um das gesamte Skript" verstehen? somefunction() ( ... ) (Beachten Sie die Parens anstelle von Locken) somefunctionEs ist nicht ungewöhnlich, anzugeben, dass immer eine Unterschale erstellt werden soll. Ich glaube jedoch nicht, dass tatsächliche Skripte in Klammern eingeschlossen werden müssen.
PSkocik

1
@PSkocik Ein Beispiel
hinzugefügt

1
Werfen Sie auch einen Blick auf Prozesssubstitution gegen Pipeline und Python gegen Shell-Schleifen, wenn Sie neugierig auf die Leistung in Shells im Allgemeinen sind.
Sergiy Kolodyazhnyy

Antworten:


7

Unterschalen haben Overhead.

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

Bei Subshells sprechen Sie nur von den Forking-Kosten, da keine Datei bearbeitet werden muss exec. Wenn die Unterschalen angemessen niedrig gehalten werden, 1msist dies in Programmen mit menschlichem Gesicht vernachlässigbar. Ich glaube, die Menschen können nichts bemerken, was schneller passiert als 50ms(und so lange dauert es in der Regel , bis moderne Dolmetscher für Skriptsprachen überhaupt anfangen (ich spreche pythonund bin rvmhier drin ) mit dem neuesten nodejsThema beginnen 100ms).

Es summiert sich jedoch zu Schleifen, und dann möchten Sie möglicherweise beispielsweise den häufig vorkommenden Bactick oder das $()Muster ersetzen, bei dem Sie returnetwas von einer Funktion drucken, indem Sie es auf stdout drucken, damit die übergeordnete Shell mit Bashismen wie printf -v(oder einem schnellen externen) katpure Programm zur Verarbeitung der gesamten Charge).

Das Bash-Completion- Paket vermeidet diese Subshell-Kosten speziell, indem es über übergebene Variablennamen mithilfe einer unter http://fvue.nl/wiki/Bash:_Passing_variables_by_reference beschriebenen Technik zurückgibt


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 forkSystemaufwands geben.


1
Vielen Dank. Das ist eigentlich sehr nützlich. Ich schreibe Skripte auf alten Laptops. Wenn ich ein Skript schreibe, das mehrmals aufgerufen wird, vermeide ich die Verwendung von Subshells. Auch wenn es vernachlässigbar ist, versuche ich von Anfang an, gute Codierungspraktiken zu entwickeln.
LinuxLearner

Wenn Sie Skripte für alte Laptops schreiben, geben Sie Perl 5 ein echtes Aussehen. Perl funktioniert auf fast jedem alten System. Wenn Sie sich an die Syntax 5.008 oder 5.010 halten, haben Sie Zugriff auf massiv mehr Geschwindigkeit und Leistung als die Shell. Ich habe die Shell-Route aus guten Gründen zu viele Jahre lang durchgeführt, aber am Ende entschied ich, dass ich es tun werde, wenn ich beides konsistent benötige, zum Teil, weil ich immer Funktionsrückgaben über Subshells erhalten musste und keine komplexen Datenstrukturen hatte benutze Perl. Die Gabelkosten sind enorm, wenn Sie auf echte Schleifen treffen. Es ist nicht zu unterschätzen. Perl ist ungefähr 2x schneller.
Lizardx

1
Ich habe kürzlich einige (z. B.) $(echo $text | cut ...)Aufrufe, die Teilzeichenfolgen aus Text extrahieren, durch ${text##substr}Aufrufe ersetzt und die Ausführungszeit drastisch reduziert.
user208145

1

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

Dieses Beispiel trifft jedoch wirklich auf native Befehle im Vergleich zu Subshell-Befehlen:

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     
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.