Sepertinya find
harus memeriksa apakah jalur yang diberikan sesuai dengan file atau direktori tetap untuk berjalan secara rekursif isi direktori.
Inilah beberapa motivasi dan apa yang telah saya lakukan secara lokal untuk meyakinkan diri saya bahwa find . -type f
sebenarnya lebih lambat daripada find .
. Saya belum menggali kode sumber menemukan GNU.
Jadi saya membuat cadangan beberapa file di $HOME/Workspace
direktori saya , dan mengecualikan file yang merupakan dependensi dari proyek saya atau file kontrol versi.
Jadi saya menjalankan perintah berikut yang dijalankan dengan cepat
% find Workspace/ | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-and-dirs.txt
find
disalurkan ke grep
bentuk yang buruk, tetapi sepertinya cara paling langsung untuk menggunakan filter regex yang dinegasikan.
Perintah berikut hanya menyertakan file dalam output dari find dan memakan waktu lebih lama.
% find Workspace/ -type f | grep -v '/vendor\|/node_modules/\|Workspace/sources/\|/venv/\|/.git/' > ws-files-only.txt
Saya menulis beberapa kode untuk menguji kinerja kedua perintah ini (dengan dash
dan tcsh
, hanya untuk mengesampingkan efek yang mungkin dimiliki shell, meskipun seharusnya tidak ada). The tcsh
hasil telah dihilangkan karena mereka pada dasarnya sama.
Hasil yang saya dapatkan menunjukkan penalti kinerja 10% untuk -type f
Berikut ini output dari program yang menunjukkan jumlah waktu yang dibutuhkan untuk menjalankan 1000 iterasi dari berbagai perintah.
% 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
Diuji dengan
% find --version
find (GNU findutils) 4.4.2
Copyright (C) 2007 Free Software Foundation, Inc.
Di Ubuntu 15.10
Inilah skrip perl yang saya gunakan untuk pembandingan
#!/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
dan tanpa itu. Tetapi pada saat pertama kernel Linux memuatnya ke dalam cache dan penemuan pertama lebih lambat.
-type f
opsi menyebabkan find
panggilan stat()
atau fstat()
atau apa pun untuk mengetahui apakah nama file sesuai dengan file, direktori, symlink, dll. Saya melakukan strace
pada find .
dan find . -type f
dan jejak hampir identik, hanya berbeda dalam write()
panggilan yang memiliki nama direktori di dalamnya. Jadi, saya tidak tahu, tetapi saya ingin tahu jawabannya.
time
perintah builtin untuk melihat berapa lama perintah untuk dieksekusi, Anda tidak benar-benar perlu menulis skrip khusus untuk diuji.
find
harus memeriksa apakah jalur yang diberikan sesuai dengan file atau direktori tetap untuk berjalan secara rekursif isi direktori. - harus memeriksa apakah itu direktori, tidak perlu memeriksa apakah itu file. Ada jenis entri lain: pipa bernama, tautan simbolik, blok perangkat khusus, soket ... Jadi, meskipun mungkin sudah melakukan pemeriksaan untuk melihat apakah itu direktori, itu tidak berarti ia tahu apakah itu file biasa.