GNU/Linux >> Linux Esercitazione >  >> Linux

Perché `trova . -type F` impiega più tempo di `find .`?

Sembra find dovrebbe comunque verificare se un determinato percorso corrisponde a un file o una directory per poter percorrere ricorsivamente il contenuto delle directory.

Ecco alcune motivazioni e cosa ho fatto a livello locale per convincermi che find . -type f è davvero più lento di find . . Non ho ancora scavato nel codice sorgente di GNU find.

Quindi sto eseguendo il backup di alcuni dei file nel mio $HOME/Workspace directory ed escludendo i file che sono dipendenze dei miei progetti o file di controllo della versione.

Quindi ho eseguito il seguente comando che è stato eseguito rapidamente

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

find reindirizzato a grep potrebbe essere una cattiva forma, ma sembrava il modo più diretto per utilizzare un filtro regex negato.

Il comando seguente include solo i file nell'output di trova e ha richiesto molto più tempo.

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

Ho scritto del codice per testare le prestazioni di questi due comandi (con dash e tcsh , giusto per escludere eventuali effetti che la shell potrebbe avere, anche se non dovrebbero essercene). Il tcsh i risultati sono stati omessi perché sono essenzialmente gli stessi.

I risultati che ho ottenuto hanno mostrato una penalizzazione delle prestazioni del 10% per -type f

Ecco l'output del programma che mostra il tempo impiegato per eseguire 1000 iterazioni di vari comandi.

% 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

Testato con

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

Su Ubuntu 15.10

Ecco lo script perl che ho usato per il benchmarking

#!/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);
    }
}

Risposta accettata:

GNU find ha un'ottimizzazione che può essere applicata a find . ma non per find . -type f :se sa che nessuna delle voci rimanenti in una directory sono directory, allora non si preoccupa di determinare il tipo di file (con il stat chiamata di sistema) a meno che uno dei criteri di ricerca non lo richieda. Chiamando stat può richiedere un tempo misurabile poiché le informazioni si trovano in genere nell'inode, in una posizione separata sul disco, piuttosto che nella directory che le contiene.

Correlati:pianificare il lavoro a intervalli irregolari?

Come fa a saperlo? Perché il conteggio dei collegamenti su una directory indica quante sottodirectory ha. Sui tipici filesystem Unix, il conteggio dei collegamenti di una directory è 2 più il numero di directory:una per la voce della directory nel suo genitore, una per il . voce e uno per il .. voce in ogni sottodirectory.

Il -noleaf l'opzione dice find di non applicare questa ottimizzazione. Questo è utile se find viene invocato su alcuni filesystem in cui i conteggi dei collegamenti alle directory non seguono la convenzione Unix.


Linux
  1. Perché /bin/sh punta a /bin/dash e non a /bin/bash??

  2. Come scoprire da quale cartella è in esecuzione un processo?

  3. Perché un tentativo di password errata richiede molto più tempo per l'elaborazione rispetto a uno corretto?

  4. Perché Linux elenca le unità NVMe come /dev/nvme0 invece di /dev/sda?

  5. Perché mettere cose diverse da /home in una partizione separata?

Quando dovrei usare /dev/shm/ e quando dovrei usare /tmp/?

Perché questa espressione regolare non funziona su Linux?

Perché Linux usa una partizione di swap piuttosto che un file?

Perché su alcuni sistemi Linux, il filesystem di root appare come /dev/root invece di /dev/<real device node>in mtab?

Perché sono necessari < o > per usare /dev/tcp

I siti web dovrebbero vivere in /var/ o /usr/ in base all'utilizzo consigliato?