Neden “ls *” “ls” den daha uzun sürüyor?


28

Bir dizinde birkaç dosya var:

$ ls | wc -l
9376

Kullanarak böyle büyük zaman farkı vardır neden kimse açıklayabilir ls *ve ls?

$ time ls > /dev/null
real    0m0.118s
user    0m0.106s
sys     0m0.011s

ve

$ time ls * > /dev/null
real    1m32.602s
user    0m0.233s
sys     0m0.438s

Tamam, bu çok sert bir örnek ve belki de geliştirilmiş çünkü dizin genel bir paralel dosya sisteminde (GPFS). Ancak yerel bir dosya sisteminde de önemli bir yavaşlama görebiliyorum.

DÜZENLE:

$ 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

ve benim örneğimde alt dizinlerin olmadığını da eklemeliyim:

$ diff <(ls) <(ls *)
$

Yanıtlar:


47

lsArgümanlar olmadan çalıştırdığınızda , sadece bir dizin açacak, tüm içerikleri okuyacak, sıralayabilecek ve yazdırabilirsiniz.

Çalıştırdığınızda ls *, ilk önce kabuk genişler *, ki basit olanlarla aynıdır ls, geçerli dizindeki tüm dosyalar ile bir argüman vektörü oluşturur ve çağırır ls. lso zaman bu argüman vektörünü ve her argüman için işlem yapmak zorundadır ve access(2)varlığını kontrol etmek için dosyayı çağırır . Ardından, ilk çıktıyla aynı çıktıyı basar (basit) ls. Hem kabuğun büyük argüman vektörünü işlemesi hem de lsbiraz zaman alabilen küçük blokların çok fazla bellek tahsisi yapılması gerekecektir. Bununla birlikte, çok az zaman sysve userçok fazla realzaman olduğu için, çoğu zaman, bellek ayırma yapan CPU kullanmak yerine, çoğu zaman disk beklemeye harcanırdı.

Her bir çağrı access(2), izin bilgisini almak için dosyanın inode'unu okumalıdır. Bu, sadece bir dizini okumaktan çok daha fazla diskin okuduğunu ve aradığı anlamına gelir. Bu işlemlerin GPFS’nizde ne kadar pahalı olduğunu bilmiyorum, ancak ls -ljoker karakter durumuyla benzer çalışma süresine sahip olduğunu gösterdiğiniz karşılaştırmada , inode bilgisini almak için gereken süre baskın görünüyor. GPFS, her okuma işleminde yerel dosya sisteminizden biraz daha yüksek gecikme süresine sahipse, bu durumlarda daha belirgin olmasını bekleriz.

Joker karakter ve ls -l% 50 arasındaki fark , diskteki inode'ların sıralaması ile açıklanabilir. İnode'lar dizindeki dosya isimleriyle aynı sırada art arda dizildiyse ve ls -lsıralamadan önce (2) dosyaları dizin sırasına göre dizdiyseniz, ls -lmuhtemelen inode'ların çoğunu bir taramada okuyabilirdi. Joker karakterle kabuk, dosya adlarını iletmeden önce sıralar, lsbu nedenle lsinode'ları farklı bir sırayla okur ve daha fazla disk kafası hareketi ekler.

Sizin unutulmamalıdır timeçıktı joker genişletmek için kabuk için gerekli süreyi içermez.

Neler olup bittiğini gerçekten görmek istiyorsanız, şunu kullanın strace(1):

strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *

ve her durumda hangi sistem çağrılarının yapıldığına bir bakın.

Actually access(2)Gerçekten kullanılıp kullanılmadığını veya başka bir şey olup olmadığını bilmiyorum stat(2). Fakat her ikisi de muhtemelen bir inode araması gerektiriyor (inode aramasını access(file, 0)atlayıp atlamayacağından emin değilim .)


2
İyi cevap, sadece yaklaşık bir benzerini :) sonrası oldu Ama birlikte evet, bu doğrudur, bu döngü içinde verimliliği hakkında hepsi lssadece "düğümünün çocukları için hangi dosya sistemini sorabilir pwdnerede olduğu gibi" ls *"inode'nin çocukları (ve dosya nedir?) a" ardından b, c, d, vb.
NJ

@ NJ bir sorgu vs birçok şimdiye kadar iyi bir özetidir. @ camh: ayrıntılı cevap için teşekkürler. Ben de çıkışını gönderdim ls -l(hala yaklaşık 30 saniye daha az ls *)
Sebastian

@Sebastian CAMH belirterek, şöyle ls -ldaha uzun sürer lso kadar olduğu gibi stat(2)vb damgaları / sahibi bilgilerine / izinleri hakkında bilgi almak için her dosya
NJ

6
Unutmayın *için globs tüm alt dizin adları dahil - bir dönemle başlamayın geçerli dizinde girdileri. Hangisi daha sonra lsbasılacak.
Shadur

@camh: I (Düzenlemelerimi bakınız) biraz daha test edilmiş ve tespit: ls< ls -l< ls -l *< ls *(Hep bunu üç kez koştu). Açıklamanla, neden ls -l *daha hızlı olduğunu anlamıyorumls *
Sebastian
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.