GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Warum findet `find . -type F` dauert länger als `find .`?

Es scheint wie find müsste prüfen, ob ein gegebener Pfad ohnehin einer Datei oder einem Verzeichnis entspricht, um den Inhalt von Verzeichnissen rekursiv zu durchlaufen.

Hier ist etwas Motivation und was ich vor Ort getan habe, um mich davon zu überzeugen, dass find . -type f ist wirklich langsamer als find . . Ich habe mich noch nicht mit dem Quellcode von GNU find beschäftigt.

Also sichere ich einige der Dateien in meinem $HOME/Workspace Verzeichnis und schließt Dateien aus, die entweder Abhängigkeiten meiner Projekte oder Versionskontrolldateien sind.

Also habe ich den folgenden Befehl ausgeführt, der schnell ausgeführt wurde

% find Workspace/ | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > ws-files-and-dirs.txt

find an grep geleitet mag ein schlechter Stil sein, aber es schien der direkteste Weg zu sein, einen negierten Regex-Filter zu verwenden.

Der folgende Befehl bezieht nur Dateien in die Ausgabe von find ein und dauert deutlich länger.

% find Workspace/ -type f | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > ws-files-only.txt

Ich habe Code geschrieben, um die Leistung dieser beiden Befehle zu testen (mit dash und tcsh , nur um mögliche Auswirkungen der Shell auszuschließen, obwohl es keine geben sollte). Der tcsh Ergebnisse wurden weggelassen, da sie im Wesentlichen gleich sind.

Die Ergebnisse, die ich erhalten habe, zeigten eine Leistungseinbuße von etwa 10 % für -type f

Hier ist die Ausgabe des Programms, die zeigt, wie viel Zeit benötigt wird, um 1000 Iterationen verschiedener Befehle auszuführen.

% perl tester.pl
/bin/sh -c find Workspace/ >/dev/null
82.986582

/bin/sh -c find Workspace/ | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > /dev/null
90.313318

/bin/sh -c find Workspace/ -type f >/dev/null
102.882118

/bin/sh -c find Workspace/ -type f | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > /dev/null

109.872865

Getestet mit

% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.

Unter Ubuntu 15.10

Hier ist das Perl-Skript, das ich für das Benchmarking verwendet habe

#!/usr/bin/env perl
use strict;
use warnings;
use Time::HiRes qw[gettimeofday tv_interval];

my $max_iterations = 1000;

my $find_everything_no_grep = <<'EOF';
find Workspace/ >/dev/null
EOF

my $find_everything = <<'EOF';
find Workspace/ | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > /dev/null
EOF

my $find_just_file_no_grep = <<'EOF';
find Workspace/ -type f >/dev/null
EOF

my $find_just_file = <<'EOF';
find Workspace/ -type f | grep -v '/vendor|/node_modules/|Workspace/sources/|/venv/|/.git/' > /dev/null
EOF

my @finds = ($find_everything_no_grep, $find_everything,
    $find_just_file_no_grep, $find_just_file);

sub time_command {
    my @args = @_;
    my $start = [gettimeofday()];
    for my $x (1 .. $max_iterations) {
        system(@args);
    }
    return tv_interval($start);
}

for my $shell (["/bin/sh", '-c']) {
    for my $command (@finds) {
        print "@$shell $command";
        printf "%snn", time_command(@$shell, $command);
    }
}

Akzeptierte Antwort:

GNU find hat eine Optimierung, die auf find . angewendet werden kann aber nicht find . -type f :Wenn es weiß, dass keiner der verbleibenden Einträge in einem Verzeichnis Verzeichnisse sind, dann macht es sich nicht die Mühe, den Dateityp zu bestimmen (mit dem stat Systemaufruf), es sei denn, eines der Suchkriterien erfordert dies. Aufruf von stat kann messbar viel Zeit in Anspruch nehmen, da sich die Informationen normalerweise im Inode an einem separaten Ort auf der Festplatte und nicht im enthaltenden Verzeichnis befinden.

Verwandte:Job in unregelmäßigen Abständen planen?

Woher weiß es? Denn die Linkanzahl eines Verzeichnisses gibt an, wie viele Unterverzeichnisse es hat. Auf typischen Unix-Dateisystemen beträgt die Anzahl der Verknüpfungen eines Verzeichnisses 2 plus die Anzahl der Verzeichnisse:eine für den Eintrag des Verzeichnisses in seinem übergeordneten Verzeichnis, eine für den . -Eintrag und eine für .. Eintrag in jedem Unterverzeichnis.

Das -noleaf Option sagt find diese Optimierung nicht anzuwenden. Dies ist nützlich, wenn find wird in einigen Dateisystemen aufgerufen, in denen die Anzahl der Verzeichnislinks nicht der Unix-Konvention entspricht.


Linux
  1. Warum gibt Find -mtime +1 nur Dateien zurück, die älter als 2 Tage sind?

  2. Linux – Warum dauert es so lange, einen USB-Stick zu erkennen?

  3. Wie finde ich heraus, aus welchem ​​Ordner ein Prozess läuft?

  4. Warum dauert die Verarbeitung eines falschen Kennwortversuchs viel länger als bei einem korrekten?

  5. Warum funktioniert diese Regex nicht unter Linux?

Wann sollte ich /dev/shm/ verwenden und wann sollte ich /tmp/?

Warum listet Linux NVMe-Laufwerke als /dev/nvme0 anstelle von /dev/sda auf?

Warum verwendet Linux eine Swap-Partition und keine Datei?

Warum ändert sich MemTotal in /proc/meminfo?

Warum dauert die Erkennung eines USB-Sticks so lange?

Sollten Websites gemäß der empfohlenen Verwendung in /var/ oder /usr/ leben?