GNU/Linux >> Znalost Linux >  >> Linux

Proč najde . -type F` Trvat déle než `najít .`?

Vypadá to jako find musel by stejně zkontrolovat, zda daná cesta odpovídá souboru nebo adresáři, aby mohl rekurzivně projít obsah adresářů.

Zde je určitá motivace a to, co jsem udělal lokálně, abych se přesvědčil, že find . -type f je opravdu pomalejší než find . . Ještě jsem se nehrabal ve zdrojovém kódu GNU find.

Takže zálohuji některé soubory v mém $HOME/Workspace adresář a vyjma souborů, které jsou buď závislostmi mých projektů, nebo soubory správy verzí.

Spustil jsem tedy následující příkaz, který se rychle provedl

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

find přesměrováno do grep může být špatná forma, ale zdálo se to jako nejpřímější způsob použití filtru negovaného regulárního výrazu.

Následující příkaz obsahuje pouze soubory ve výstupu find a trval znatelně déle.

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

Napsal jsem nějaký kód, abych otestoval výkon těchto dvou příkazů (s dash a tcsh , jen abychom vyloučili jakékoli účinky, které by shell mohl mít, i když by žádné neměly být). tcsh výsledky byly vynechány, protože jsou v podstatě stejné.

Výsledky, které jsem dostal, ukázaly asi 10% penalizaci výkonu pro -type f

Zde je výstup programu ukazující množství času potřebného k provedení 1000 iterací různých příkazů.

% 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

Testováno pomocí

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

Na Ubuntu 15.10

Zde je skript perl, který jsem použil pro srovnávání

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

Přijatá odpověď:

GNU find má optimalizaci, kterou lze použít na find . ale ne k find . -type f :pokud ví, že žádná ze zbývajících položek v adresáři nejsou adresáře, pak se neobtěžuje určit typ souboru (pomocí stat systémové volání), pokud to jedno z vyhledávacích kritérií nevyžaduje. Volání stat může trvat měřitelný čas, protože informace jsou obvykle v inodu, na samostatném místě na disku, nikoli v adresáři, který obsahuje.

Související:Plánovat práci v nepravidelných intervalech?

jak to ví? Protože počet odkazů na adresář udává, kolik podadresářů má. Na typických unixových souborových systémech je počet odkazů na adresář 2 plus počet adresářů:jeden pro záznam adresáře v jeho rodiči, jeden pro . záznam a jeden pro .. záznam v každém podadresáři.

-noleaf volba říká find tuto optimalizaci nepoužít. To je užitečné, pokud find je vyvolán na některých souborových systémech, kde počty odkazů na adresáře neodpovídají unixové konvenci.


Linux
  1. Jak Linux zpracovává více po sobě jdoucích oddělovačů cest (/home////username///soubor)?

  2. Linux – Proč detekce USB Stick trvá tak dlouho?

  3. Kdy mám použít /dev/shm/ a kdy /tmp/?

  1. Jak zjistit, ze které složky běží proces?

  2. Proč by zpracování nesprávného hesla trvalo mnohem déle než správného?

  3. Proč dávat věci jiné než /home do samostatného oddílu?

  1. Proč Linux používá odkládací oddíl místo souboru?

  2. Proč se na některých systémech Linux kořenový souborový systém zobrazuje jako /dev/root místo /dev/<uzel skutečného zařízení>v mtab?

  3. Proč spuštění příkazu sudo trvá dlouho?