Wie wirkt sich die Reihenfolge der Argumente in einem find
Aufruf auf die Geschwindigkeit der Ergebnisse aus?
Vergleiche zum Beispiel (A)
find -name dir -type d
und B)
find -type d -name dir
Oder eine andere Kombination von Argumenten (z . B. mit -or
oder -and
). Ich würde erwarten find
, irgendwie schlau zu sein.
Ich habe versucht, einige Statistiken zu sammeln, indem ich sowohl A als auch B mit time
und 5 Wiederholungen ausgeführt habe. Jedoch mit
11.86, 7.23, 5.25, 5.87, 7.16
für A und für B:
9.73, 6.56, 8.69, 7.14, 6.35
Dies ist nicht wirklich schlüssig, mit Mittelwerten 7.5s
für beide und einer ziemlich hohen Varianz.
Um meine Frage zu wiederholen, spielt die Reihenfolge der Argumente eine Rolle find
?
-name ..
und von-type d
Bedeutung ist. Ihre Tests scheinen darauf hinzudeuten, dass dies nicht der Fall ist.find
auslösenden Dateiereignisse verfolgen, die Sie zu einem genaueren Bild davon führen sollten, welche Dateien während derfind
Ausführung "berührt" werden .Antworten:
Was teuer ist, sind Systemaufrufe für die Dateien (für die Systemaufrufe selbst und für die E / A).
Solche Dinge
-type
,-mtime
erfordern einenlstat(2)
auf dem Dateisystemaufruf.-name
,-path
,-regex
Nicht (obwohl natürlich wird es getan Systemaufrufe auf die Verzeichnisse haben sie enthalten , ihre Inhalte zu lesen).In der
find
Regel wird einelstat()
ohnehin (weil es wissen muss, ob eine Datei ein Verzeichnis ist oder nicht, um in sie abzusteigen, es sei denn, diese Informationen sind im enthaltenreaddir()
), aber es gibt Fälle, in denen es ohne sie auskommen kann. Wenn beispielsweise die Anzahl der Links eines Verzeichnisses weniger als 3 beträgt,find
weiß es in einigen Dateisystemen, dass es keine Unterverzeichnisse hat, und einigefind
Implementierungen werden optimiert, indem dort keinlstat
s ausgeführt wird.-xtype
wird ein verursachenstat(2)
,-printf ...
,-ls
verursachen einstat()
,lstat()
,readlink()
,-lname
alstat()
undreadlink()
.Deshalb möchten Sie vielleicht das
-name
/-path
/-regex
... an die erste Stelle setzen. Wenn sie eine Datei ausschließen können, können sie einen oder mehrere Systemaufrufe vermeiden.Nun, ein ist
-regex
vielleicht teurer als ein-name
, aber ich bin mir nicht sicher, ob Sie durch den Austausch viel erreichen würden.Beachten Sie auch, dass einige
find
Implementierungen wie GNUfind
die Prüfungen nach Möglichkeit standardmäßig neu anordnen. Sehen:auf einem GNU-System ( dort auf gnu.org für die neueste Version von GNU
findutils
).Wenn Sie Ihre Tests auf einem GNU-System durchgeführt hätten, würden beide Befehle normalerweise dasselbe tun, da
find
sie den-name
Vorgang ohnehin vorwärts verschoben hätten .Damit das
-type d -name ...
vs-name ... -type d
einen Unterschied macht, benötigen Sie einefind
Implementierung, die nicht durch Neuanordnen dieser Prädikate optimiert wird, und eine Implementierung, die einige Optimierungen vornimmt, indem nichtlstat()
für jede Datei eine durchgeführt wird.Wo es unabhängig von der Implementierung einen (großen) Unterschied geben wird, ist:
vs:
find
Ich kann das nicht neu anordnen,-exec
da dies zu Funktionsunterschieden führen kann (find
ich kann nicht wissen, ob der ausgeführte Befehl nur zum Testen dient oder etwas anderes tut).Und natürlich
-exec ... {} \;
ist es mehrere Größenordnungen teurer als jedes andere Prädikat, da es bedeutet, einen Prozess zu verzweigen und einen Befehl darin auszuführen (der selbst viele Systemaufrufe ausführt) und auf ihn und seinen Exit-Code zu warten.(Die erste ruft
test
jede Datei in/usr/lib
(56685) auf, die zweite nur für die Dateien, deren Name mitz
(147) beginnt .)Beachten Sie, dass dies
-exec test -d {} \;
nicht dasselbe ist wie-type d
. Es ist das tragbare Äquivalent der GNU-spezifischen-xtype d
.quelle
find
muss, ob eine Datei ausgewählt ist oder nicht, ist es besser, die Überprüfungen, die keinen Systemaufruf beinhalten, zuerst zu setzen.-exec
Beweis ist ziemlich nett :)