Кажется, find
что в любом случае придется проверить, соответствует ли данный путь файлу или каталогу, чтобы рекурсивно просмотреть содержимое каталогов.
Вот некоторая мотивация и то, что я сделал на местном уровне, чтобы убедить себя, что на find . -type f
самом деле медленнее, чем find .
. Я еще не копался в GNU найти исходный код.
Поэтому я создаю резервные копии некоторых файлов в моем $HOME/Workspace
каталоге и исключаю файлы, которые являются либо зависимостями моих проектов, либо файлами контроля версий.
Итак, я запустил следующую команду, которая выполнялась быстро
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
find
Это grep
может быть плохая форма, но это кажется самым прямым способом использования отрицательного фильтра регулярных выражений.
Следующая команда включает в себя только файлы в выводе find и заняла заметно больше времени.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Я написал некоторый код для проверки производительности этих двух команд (с dash
и tcsh
, просто чтобы исключить любые эффекты, которые может иметь оболочка, даже если их не должно быть). Эти tcsh
результаты были опущены , поскольку они по существу то же самое.
Результаты, которые я получил, показали около 10% снижения производительности за -type f
Вот выходные данные программы, показывающие количество времени, необходимое для выполнения 1000 итераций различных команд.
% 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
Протестировано с
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
На Ubuntu 15.10
Вот скрипт Perl, который я использовал для бенчмаркинга
#!/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 "%s\n\n", time_command(@$shell, $command);
}
}
-type f
и без него. Но вначале ядро Linux загрузило его в кеш, и самая первая находка была медленнее.
-type f
параметр вызвал find
вызов stat()
или fstat()
что-то еще, чтобы выяснить, соответствует ли имя файла файлу, каталогу, символической ссылке и т. Д. И т. Д. Я сделал strace
on find .
и a, find . -type f
и трассировка была почти идентична, отличается только write()
вызовами, в которых были имена каталогов. Итак, я не знаю, но я хочу знать ответ.
time
встроенная команда, чтобы увидеть, сколько времени занимает выполнение команды, вам не нужно было писать собственный скрипт для тестирования.
find
что в любом случае придется проверить, соответствует ли данный путь файлу или каталогу, чтобы рекурсивно просмотреть содержимое каталогов. - он должен проверить, является ли он каталогом, он не должен проверять, является ли он файлом. Существуют и другие типы записей: именованные каналы, символические ссылки, блочные специальные устройства, сокеты ... Так что, возможно, он уже выполнил проверку, чтобы определить, является ли это каталогом, но это не значит, что он знает, является ли он обычным файлом.