Ist es gleichbedeutend damit, dass Befehle direkt in eine Datei gedruckt werden, anstatt in einen Dateideskriptor zu schreiben?
Illustration
Direkt in die Datei schreiben:
for i in {1..1000}; do >>x echo "$i"; done
Verwenden eines fd:
exec 3>&1 1>x
for i in {1..1000}; do echo "$i"; done
exec 1>&3 3>&-
Ist letzteres effizienter?
bash
shell
io-redirection
file-descriptors
optimization
Gilles 'SO - hör auf böse zu sein'
quelle
quelle
write(2)
zu einem Dateideskriptor, wie denkst du ist einer "direkter"?for i in {1..1000}; do echo "$i"; done > x
? Das öffnet die Datei nur einmal.Antworten:
Der Hauptunterschied zwischen dem Öffnen der Datei vor der Schleife mit
exec
und dem Einfügen der Umleitung in den Befehl in die Schleife besteht darin, dass beim ersteren der Dateideskriptor nur einmal eingerichtet werden muss, während beim letzteren die Datei für jede Iteration der Schleife geöffnet und geschlossen wird.Dies einmal zu tun ist wahrscheinlich effizienter, aber wenn Sie einen externen Befehl innerhalb der Schleife ausführen würden, würde der Unterschied wahrscheinlich in den Kosten für das Starten des Befehls verschwinden. (
echo
hier ist wahrscheinlich eingebaut, das gilt also nicht)Wenn die Ausgabe an eine andere als eine reguläre Datei gesendet werden soll (z. B. wenn
x
es sich um eine Named Pipe handelt), kann das Öffnen und Schließen der Datei für andere Prozesse sichtbar sein, sodass es auch zu Verhaltensunterschieden kommen kann.Beachten Sie, dass es wirklich keinen Unterschied zwischen einer Umleitung durch
exec
und einer Umleitung im Befehl gibt. Beide öffnen die Datei und jonglieren mit den Dateideskriptornummern.Diese beiden sollten ziemlich gleichwertig sein, da sie sowohl
open()
die Datei als auchwrite()
dazu sind. (Es gibt jedoch Unterschiede in der Speicherung von fd 1 für die Dauer des Befehls.):quelle
for i in {1..1000}; do echo $i; done >x
. Ich würde sagen, dies ist die am besten lesbare Version.Ja, es ist effizienter
Der einfachste Weg zum Testen besteht darin, die Anzahl auf 500000 zu erhöhen und die Zeit festzulegen:
strace (1) zeigt warum (wir haben eine einfache
write
anstelle vonopen
+ 5 *fcntl
+ 2 *dup
+ 2 *close
+write
):denn
for i in {1..1000}; do >>x echo "$i"; done
wir bekommen:während
exec 3>&1 1>x
wir viel sauberer werdenBeachten Sie jedoch, dass der Unterschied nicht auf die Verwendung eines FD zurückzuführen ist, sondern auf den Ort, an dem Sie die Umleitung durchführen. Wenn Sie dies beispielsweise tun
for i in {1..1000}; do echo "$i"; done > x
würden, würden Sie fast die gleiche Leistung wie in Ihrem zweiten Beispiel erzielen:quelle
Um die Dinge zusammenzufassen und neue Informationen in diesen Thread aufzunehmen, finden Sie hier einen Vergleich von vier Möglichkeiten, geordnet nach Effizienz. Ich schätze die Effizienz durch Zeitmessung (Benutzer + System) für 1 Million Iterationen basierend auf zwei Testreihen.
>
Schleifenumleitung (Zeit: 100% )exec
einmal für die gesamte Schleife (Zeit: ~ 100% )>>
für jede Iteration (Zeit: 200% - 250% )exec
für jede Iteration (Zeit: 340% - 480% )Die Schlussfolgerung lautet:
Es gibt einen kleinen Unterschied zwischen der Verwendung
exec
und einfachen Umleitungen wie>>
. (Einfach ist billiger). Es wird nicht auf der Ebene der Ausführung eines einzelnen Befehls angezeigt, aber bei einer hohen Anzahl von Wiederholungen wird der Unterschied sichtbar. Obwohl das Ausführungsgewicht des Befehls auf die Unterschiede umgeleitet wurde, wie von ikkachu in der anderen Antwort bemerkt.quelle
seq 1000
oder möglicherweiseprintf "%s\n" {1..1000}
schneller als eine Bash-Schleife sind. (seq 1000000 > /dev/null
Läufttime printf "%s\n" {1..1000000} > /dev/null
in ~ 0,03 s, in ~ 0,7 s,time for i in {1..1000000}; do echo "$i"; done > /dev/null
in 2,1 s auf einem 3,9 GHz Skylake i7-6700k, Linux 4.15.8-1-ARCH.printf
vs. Fork + Exec von liegtseq
. Ich denke, ich könnte eine Wiederholungsschleife um das Ganze wickeln und das mal. Übrigenstime awk 'BEGIN{ for(i=1; i<1000000 ; i++) {print i}}' > /dev/null
ist es ungefähr dreimal schneller alsprintf "%s\n" {1..1000000}
, selbst wenn Sie es nicht habenseq
, kann eine gute AWK-Implementierung integrierte Funktionen für große Problemgrößen übertreffen.