GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué `find . -type F` ¿Toma más tiempo que `find .`?

Parece que find tendría que verificar si una ruta determinada corresponde a un archivo o directorio de todos modos para recorrer recursivamente el contenido de los directorios.

Aquí hay algo de motivación y lo que he hecho localmente para convencerme de que find . -type f realmente es más lento que find . . Todavía no he profundizado en el código fuente de búsqueda de GNU.

Así que estoy haciendo una copia de seguridad de algunos de los archivos en mi $HOME/Workspace directorio y excluyendo los archivos que son dependencias de mis proyectos o archivos de control de versiones.

Así que ejecuté el siguiente comando que se ejecutó rápidamente

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

find canalizado a grep puede ser una mala forma, pero parecía la forma más directa de usar un filtro de expresiones regulares negado.

El siguiente comando incluye solo archivos en la salida de find y tomó mucho más tiempo.

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

Escribí un código para probar el rendimiento de estos dos comandos (con dash y tcsh , solo para descartar cualquier efecto que pueda tener el caparazón, aunque no debería haber ninguno). El tcsh se han omitido los resultados porque son esencialmente los mismos.

Los resultados que obtuve mostraron una penalización de rendimiento del 10 % para -type f

Aquí está el resultado del programa que muestra la cantidad de tiempo necesario para ejecutar 1000 iteraciones de varios comandos.

% 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

Probado con

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

En Ubuntu 15.10

Aquí está el script de Perl que utilicé para la evaluación comparativa

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

Respuesta aceptada:

GNU find tiene una optimización que se puede aplicar a find . pero no para find . -type f :si sabe que ninguna de las entradas restantes en un directorio son directorios, entonces no se molesta en determinar el tipo de archivo (con stat llamada del sistema) a menos que uno de los criterios de búsqueda lo requiera. Llamando a stat puede llevar un tiempo medible ya que la información normalmente está en el inodo, en una ubicación separada en el disco, en lugar del directorio contenedor.

Relacionado:¿Programar trabajo a intervalos irregulares?

¿Cómo lo sabe? Porque el recuento de enlaces en un directorio indica cuántos subdirectorios tiene. En los sistemas de archivos típicos de Unix, el recuento de enlaces de un directorio es 2 más el número de directorios:uno para la entrada del directorio en su padre, uno para el . entrada y otra para el .. entrada en cada subdirectorio.

El -noleaf opción le dice a find para no aplicar esta optimización. Esto es útil si find se invoca en algún sistema de archivos donde los recuentos de enlaces de directorio no siguen la convención de Unix.


Linux
  1. ¿Por qué Find -mtime +1 solo devuelve archivos de más de 2 días?

  2. Linux:¿por qué se tarda tanto en detectar una memoria USB?

  3. ¿Por qué find -exec mv {} ./target/ + no funciona?

  4. ¿Por qué Linux enumera las unidades NVMe como /dev/nvme0 en lugar de /dev/sda?

  5. ¿Por qué Linux usa una partición de intercambio en lugar de un archivo?

¿Por qué esta expresión regular no funciona en Linux?

¿Por qué poner otras cosas que no sean /home en una partición separada?

¿Por qué se tarda tanto en detectar una memoria USB?

¿Por qué se requieren < o > para usar /dev/tcp?

¿Por qué el comando Sudo tarda mucho en ejecutarse?

¿Deberían vivir los sitios web en /var/ o /usr/ según el uso recomendado?