GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi `find . -type F` Prend plus de temps que `find .`?

Il semble que find devrait de toute façon vérifier si un chemin donné correspond à un fichier ou à un répertoire afin de parcourir récursivement le contenu des répertoires.

Voici quelques motivations et ce que j'ai fait localement pour me convaincre que find . -type f est vraiment plus lent que find . . Je n'ai pas encore creusé dans le code source de recherche GNU.

Je sauvegarde donc certains des fichiers dans mon $HOME/Workspace répertoire, et en excluant les fichiers qui sont soit des dépendances de mes projets, soit des fichiers de contrôle de version.

J'ai donc exécuté la commande suivante qui s'est exécutée rapidement

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

find redirigé vers grep peut-être une mauvaise forme, mais cela semblait être le moyen le plus direct d'utiliser un filtre regex inversé.

La commande suivante inclut uniquement les fichiers dans la sortie de find et a pris sensiblement plus de temps.

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

J'ai écrit du code pour tester les performances de ces deux commandes (avec dash et tcsh , juste pour exclure tout effet que le shell pourrait avoir, même s'il ne devrait pas y en avoir). Le tcsh les résultats ont été omis car ils sont essentiellement les mêmes.

Les résultats que j'ai obtenus ont montré une pénalité de performance d'environ 10 % pour -type f

Voici la sortie du programme montrant le temps nécessaire pour exécuter 1000 itérations de diverses commandes.

% 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

Testé avec

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

Sur Ubuntu 15.10

Voici le script perl que j'ai utilisé pour l'analyse comparative

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

Réponse acceptée :

GNU find a une optimisation qui peut être appliquée à find . mais pas pour find . -type f :s'il sait qu'aucune des entrées restantes dans un répertoire n'est un répertoire, alors il ne prend pas la peine de déterminer le type de fichier (avec le stat appel système) sauf si l'un des critères de recherche l'exige. Appel de stat peut prendre un temps mesurable car les informations se trouvent généralement dans l'inode, dans un emplacement séparé sur le disque, plutôt que dans le répertoire contenant.

En relation :Planifier un travail à intervalles irréguliers ?

Comment sait-il ? Parce que le nombre de liens sur un répertoire indique le nombre de sous-répertoires dont il dispose. Sur les systèmes de fichiers Unix typiques, le nombre de liens d'un répertoire est de 2 plus le nombre de répertoires :un pour l'entrée du répertoire dans son parent, un pour le . entrée, et une pour le .. entrée dans chaque sous-répertoire.

Le -noleaf l'option indique find de ne pas appliquer cette optimisation. Ceci est utile si find est invoqué sur certains systèmes de fichiers où le nombre de liens de répertoire ne suit pas la convention Unix.


Linux
  1. Comment Linux gère-t-il plusieurs séparateurs de chemins consécutifs (/home////nom d'utilisateur///fichier) ?

  2. Quand dois-je utiliser /dev/shm/ et quand dois-je utiliser /tmp/?

  3. Pourquoi Linux répertorie-t-il les lecteurs NVMe comme /dev/nvme0 au lieu de /dev/sda ?

  4. Pourquoi cette regex ne fonctionne-t-elle pas sous Linux ?

  5. Pourquoi mettre des choses autres que /home sur une partition séparée ?

Pourquoi une tentative de mot de passe incorrect prendrait-elle beaucoup plus de temps à traiter qu'une tentative correcte ?

Pourquoi Linux utilise-t-il une partition swap plutôt qu'un fichier ?

Pourquoi MemTotal dans /proc/meminfo change-t-il ?

Pourquoi sur certains systèmes Linux, le système de fichiers racine apparaît-il comme /dev/root au lieu de /dev/<real device node> dans mtab ?

Pourquoi la commande sudo prend-elle longtemps à s'exécuter ?

Pourquoi mon nom d'hôte apparaît-il avec l'adresse 127.0.1.1 plutôt que 127.0.0.1 dans /etc/hosts ?