私のディレクトリにはいくつかのファイルがあります。
$ ls | wc -l
9376
ls *
andを使用すると、なぜこのような大きな視差が発生するのかを説明できる人はいますかls
?
$ time ls > /dev/null
real 0m0.118s
user 0m0.106s
sys 0m0.011s
そして
$ time ls * > /dev/null
real 1m32.602s
user 0m0.233s
sys 0m0.438s
いいですね。これは大胆な例であり、ディレクトリが通常の並列ファイルシステム(GPFS)にあるため、改善できます。しかし、ローカルファイルシステムでもかなりの速度低下を見ることができます。
編集する:
$ time ls -l > /dev/null
real 0m58.772s
user 0m0.113s
sys 0m0.452s
$ time ls -l * > /dev/null
real 1m19.538s
user 0m0.252s
sys 0m0.461s
私の例にはサブディレクトリがないことを追加する必要があります。
$ diff <(ls) <(ls *)
$
答え1
引数なしで実行すると、ls
ディレクトリを開き、すべての内容を読み取り、並べ替え、印刷します。
を実行すると、ls *
まずシェルが展開されます。これは、単に現在のディレクトリ内のすべてのファイルを使用して引数ベクトルを構築して呼び出す*
のと同じです。次に、対応する引数ベクトルと各引数を処理し、ファイルを呼び出して確認する必要があります。それは存在します。次に、最初の(簡単な)出力と同じ出力を印刷します。シェルの大きな引数ベクトルと合計処理には、多数の小さなメモリブロック割り当てを含めることができ、これには時間がかかる場合があります。ただし、時間が少なくてすむため、メモリ割り当てにCPUを使用するのではなく、ディスクを待つのにほとんどの時間を費やします。ls
ls
ls
access(2)
ls
ls
sys
user
real
各呼び出しでは、access(2)
資格情報を取得するためにファイルのinodeを読み取る必要があります。これは、単にディレクトリを読み取るよりも多くのディスクの読み取りとナビゲーションを意味します。 GPFSでこれらのタスクのコストがどれくらいかかるかはわかりませんが、ls -l
ワイルドカードのケースと同様のランタイム比較で示したように、inode情報を取得するのに必要な時間が支配的なようです。 GPFS がローカルファイルシステムよりも読み取り操作あたりの待ち時間が少し長い場合、この場合、待ち時間はより目立つと予想されます。
ワイルドカードケースと50%ls -l
の違いは、ディスクのinode順で説明できます。 inodeをディレクトリ内のファイル名と同じ順序で連続して配置し、ファイルをディレクトリの順序でls -l
stat(2)してソートした場合は、1回のスキャンls -l
でほとんどのinodeを読み取ることができます。ワイルドカードを使用すると、シェルがファイル名を渡す前にソートするため、ls
inodels
を別の順序で読み取ることができ、ディスクヘッドの移動が増えます。
出力には、time
シェル拡張ワイルドカードに費やされた時間は含まれません。
何が起こっているのか本当に知りたい場合は、以下を使用してくださいstrace(1)
。
strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *
各ケースでどのシステムコールが実行されているかを確認してください。
access(2)
¹それが実際に使用されているのか、それとも別のものなのかはわかりません。たとえば、両方ともinodeルックアップが必要な場合があります(inodeルックアップをバイパスするかstat(2)
どうかはわかりません)。access(file, 0)