it-swarm.com.de

Warum ist "Echo" so viel schneller als "Berührung"?

Ich versuche, den Zeitstempel für alle XML-Dateien in meinem Verzeichnis (rekursiv) auf die aktuelle Zeit zu aktualisieren. Ich verwende Mac OSX 10.8.5.

Bei ungefähr 300.000 Dateien dauert der folgende Befehl echo10 Sekunden:

for file in `find . -name "*.xml"`; do echo >> $file; done

Der folgende Befehl touch dauert jedoch 10 Minuten! ::

for file in `find . -name "*.xml"`; do touch $file; done

Warum ist Echo hier so viel schneller als Berührung?

116
Casey Patton

In bash ist touch eine externe Binärdatei, aber echo ist eine Shell integriert :

$ type echo
echo is a Shell builtin
$ type touch
touch is /usr/bin/touch

Da touch eine externe Binärdatei ist und Sie touch einmal pro Datei aufrufen, muss die Shell 300.000 Instanzen von touch erstellen, was lange dauert.

echo ist jedoch eine eingebaute Shell, und die Ausführung von eingebauten Shell erfordert überhaupt kein Forking. Stattdessen führt die aktuelle Shell alle Vorgänge aus und es werden keine externen Prozesse erstellt. das ist der Grund, warum es so viel schneller ist.

Hier sind zwei Profile der Shell-Operationen. Sie können sehen, dass bei der Verwendung von touch viel Zeit für das Klonen neuer Prozesse aufgewendet wird. Verwenden von /bin/echo anstelle der eingebauten Shell sollte ein viel vergleichbareres Ergebnis angezeigt werden.


Mit Berührung

$ strace -c -- bash -c 'for file in a{1..10000}; do touch "$file"; done'
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 56.20    0.030925           2     20000     10000 wait4
 38.12    0.020972           2     10000           clone
  4.67    0.002569           0     80006           rt_sigprocmask
  0.71    0.000388           0     20008           rt_sigaction
  0.27    0.000150           0     10000           rt_sigreturn
[...]

Echo verwenden

$ strace -c -- bash -c 'for file in b{1..10000}; do echo >> "$file"; done'
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 34.32    0.000685           0     50000           fcntl
 22.14    0.000442           0     10000           write
 19.59    0.000391           0     10011           open
 14.58    0.000291           0     20000           dup2
  8.37    0.000167           0     20013           close
[...]
160
Chris Down

Wie andere geantwortet haben, ist die Verwendung von echo schneller als touch, da echo ein Befehl ist, der üblicherweise in die Shell integriert ist (obwohl dies nicht erforderlich ist). Wenn Sie es verwenden, entfällt der Kernel-Overhead, der mit dem Starten eines neuen Prozesses für jede Datei verbunden ist, die Sie mit touch erhalten.

Beachten Sie jedoch, dass der schnellste Weg, um diesen Effekt zu erzielen, immer noch die Verwendung von touch ist. Anstatt das Programm jedoch einmal für jede Datei auszuführen, können Sie die Option -exec Mit find, um sicherzustellen, dass dies nur einige Male ausgeführt wird. Dieser Ansatz ist normalerweise schneller, da der mit einer Shell-Schleife verbundene Overhead vermieden wird:

find . -name "*.xml" -exec touch {} +

Wenn Sie + (Im Gegensatz zu \;) Mit find ... -exec Verwenden, wird der Befehl nach Möglichkeit nur einmal mit jeder Datei als Argument ausgeführt. Wenn die Argumentliste sehr lang ist (wie dies bei 300.000 Dateien der Fall ist), werden mehrere Läufe mit einer Argumentliste durchgeführt, deren Länge nahe am Grenzwert liegt (ARG_MAX Auf den meisten Systemen).

Ein weiterer Vorteil dieses Ansatzes besteht darin, dass er sich bei Dateinamen, die alle Leerzeichen enthalten, robust verhält, was bei der ursprünglichen Schleife nicht der Fall ist.

71
Graeme

echo ist eine eingebaute Shell. Andererseits ist touch eine externe Binärdatei.

$ type echo
echo is a Shell builtin
$ type touch
touch is hashed (/usr/bin/touch)

Shell Builtins sind viel schneller, da beim Laden des Programms kein Overhead anfällt, d. H. Es ist kein fork/exec beteiligt. Daher würden Sie einen signifikanten Zeitunterschied feststellen, wenn Sie einen eingebauten Befehl gegenüber einem externen Befehl mehrmals ausführen.

Aus diesem Grund sind Dienstprogramme wie time als Shell-Builtins verfügbar.

Sie können die vollständige Liste der Shell-Builds abrufen, indem Sie Folgendes sagen:

enable -p

Wie oben erwähnt, führt die Verwendung des Dienstprogramms im Gegensatz zum integrierten Dienstprogramm zu eine signifikante Leistungsverschlechterung. Im Folgenden finden Sie die Statistiken der Zeit, die zum Erstellen von ~ 9000 Dateien mit dem integrierten echo und dem benötigt wurde ) Dienstprogramm echo:

# Using builtin
$ time bash -c 'for i in {1000..9999}; do echo > $i; done'

real    0m0.283s
user    0m0.100s
sys 0m0.184s

# Using utility /bin/echo
$ time bash -c 'for i in {1000..9999}; do /bin/echo > $i; done'

real    0m8.683s
user    0m0.360s
sys 0m1.428s
29
devnull