Boru ve burada dize kullanarak kaynak kullanımı


16

Aynı sonucu aşağıdaki iki öğeyi kullanarak elde edebiliriz bash,

echo 'foo' | cat

ve

cat <<< 'foo'

Benim sorum, kullanılan kaynaklar söz konusu olduğunda ve hangisinin daha iyi olduğu konusunda bu ikisi arasındaki fark nedir?

Benim düşüncem, echopipo kullanırken, burada dizede sadece bir dosya tanımlayıcı ile kullanıldığında ekstra bir işlem ve boru kullanıyoruz cat.

Yanıtlar:


17

Boru, çekirdek içi dosya sisteminde açılan bir dosyadır ve diskteki normal bir dosya olarak erişilemez. Otomatik olarak yalnızca belirli bir boyuta arabelleğe alınır ve sonunda dolduğunda engellenir. Blok cihazlardan alınan dosyalardan farklı olarak, borular karakter cihazlarına çok benzer ve genellikle desteklemez lseek()ve onlardan okunan veriler normal bir dosyada yapabileceğiniz gibi tekrar okunamaz.

Here-string, bağlı bir dosya sisteminde oluşturulan normal bir dosyadır. Kabuk dosyayı oluşturur ve dosyaya / dosyasından bir bayt yazmadan / okumadan önce tek dosya sistemi bağlantısını hemen kaldırırken (ve böylece siler) tanımlayıcısını korur . Çekirdek, tüm işlemler dosya için tüm tanımlayıcıları serbest bırakana kadar dosya için gereken alanı koruyacaktır. Böyle bir tanımlayıcıdan okuyan çocuk bunu yapabilirse, geri sarabilir lseek()ve tekrar okuyabilir.

Her iki durumda da belirteçler <<<ve |dosya tanımlayıcıları temsil eder ve dosyaların kendileri olmak zorunda değildir. Aşağıdaki gibi şeyler yaparak neler olduğu hakkında daha iyi bir fikir edinebilirsiniz:

readlink /dev/fd/1 | cat

...veya...

ls -l <<<'' /dev/fd/*

İki dosya arasındaki en önemli fark, burada-string / doc'ın hemen hemen hepsi bir arada bir olay olmasıdır - kabuk, okuma tanımlayıcısını çocuğa sunmadan önce tüm verileri içine yazar. Öte yandan, kabuk boruyu uygun tanımlayıcılar üzerinde açar ve çocukları boru için olanları yönetmeleri için yönlendirir - ve böylece her iki uçta eşzamanlı olarak yazılır / okunur .

Ancak bu ayrımlar genellikle genel olarak doğrudur. Bildiğim kadarıyla (gerçekten o kadar da değil) bu, tek bir istisna dışında burada belge yeniden yönlendirmesi <<<için burada-string kısa-elini işleyen hemen hemen her kabuk için <<geçerlidir yash. yash, busybox, dash, Diğer ve ashvaryantları ve bu yüzden bu kabuklarda gerçekten sonuçta ikisi arasında çok az fark vardır gerçi, borularla buraya-belgeleri geri eğilimi yoktur.

Tamam - iki istisna. Şimdi düşündüğüm için, ksh93aslında hiç bir boru yapmaz |, aksine tüm iş w / soket işler - <<<*çoğu diğerleri gibi silinen bir tmp dosyası yapar. Dahası, bir boru hattının ayrı bölümlerini, en azından bir alt kabuk gibi davranan bir tür POSIX örtücüsü olan bir alt kabuk ortamına koyar ve çatalları bile yapmaz.

Gerçek şu ki, @ PSkocik'in (çok faydalı olan) karşılaştırmalı değerlendirme sonuçları birçok nedenden dolayı büyük ölçüde değişebilir ve bunların çoğu uygulamaya bağlıdır. Buradaki belge kurulumu için en büyük etkenler hedef ${TMPDIR}dosya sistemi türü ve mevcut önbellek yapılandırması / kullanılabilirliği ve yine de yazılacak veri miktarıdır. Boru için kabuk işleminin kendisi olacaktır, çünkü gerekli çatallar için kopyalar yapılır. Bu şekilde de basholduğu korkunç boru hattı kurulumu sırasında (içerecek şekilde $(komut )değiştirmelerin) - bu büyük ve çünkü çok yavaş, fakat ksh93hepsi de neredeyse hiç fark etmez.

Bir kabuğun bir boru hattı için alt kabuklardan nasıl ayrıldığını göstermek için başka bir küçük kabuk snippet'i:

pipe_who(){ echo "$$"; sh -c 'echo "$PPID"'; }
pipe_who
pipe_who | { pipe_who | cat /dev/fd/3 -; } 3<&0

32059  #bash's pid
32059  #sh's ppid
32059  #1st subshell's $$
32111  #1st subshell sh's ppid
32059  #2cd subshell's $$
32114  #2cd subshell sh's ppid

Bir Ardışık Ne arasındaki fark pipe_who()çağrı raporları ve geçerli kabuğunda bir çalışmasının raporuna bir kaynaklanmaktadır (altkabuk en )ebeveyn kabuğun pid talep etme belirtilen davranışı $$o genişletildiğinde. bashAlt $$kabuklar kesinlikle ayrı süreçler olsa da , özel kabuk parametresi bu bilgilerin güvenilir bir kaynağı değildir. Yine de, subshell'in çocuk shkabuğu, bunu doğru bir şekilde bildirmeyi reddetmez $PPID.


Çok yararlı. Çekirdek dosya sistemi, bunun için bir isim var mı? çekirdek alanında var olduğu anlamına mı geliyor?
utlamn

2
@utlamn - aslında, evet - sadece pipefs . Ama - Hepsi çekirdekteki var (kenara mal yüzünden SİGORTA gibi) böyledir tüm dosya g / ç .
mikeserv

10

Kıyaslamanın yerini tutamaz:

pskocik@ProBook:~ 
$ time (for((i=0;i<1000;i++)); do cat<<< foo >/dev/null; done  )

real    0m2.080s
user    0m0.738s
sys 0m1.439s
pskocik@ProBook:~ 
$ time (for((i=0;i<1000;i++)); do echo foo |cat >/dev/null; done  )

real    0m4.432s
user    0m2.095s
sys 0m3.927s
$ time (for((i=0;i<1000;i++)); do cat <(echo foo) >/dev/null; done  )
real    0m3.380s
user    0m1.121s
sys 0m3.423s

Daha fazla miktarda veri için:

TENMEG=$(ruby -e 'puts "A"*(10*1024*1024)')
pskocik@ProBook:~ 
$ time (for((i=0;i<100;i++)); do echo "$TENMEG" |cat >/dev/null; done  )

real    0m42.327s
user    0m38.591s
sys 0m4.226s
pskocik@ProBook:~ 
$ time (for((i=0;i<100;i++)); do cat<<< "$TENMEG" >/dev/null; done  )

real    1m26.946s
user    1m23.116s
sys 0m3.681s
pskocik@ProBook:~ 

$ time (for((i=0;i<100;i++)); do cat <(echo "$TENMEG") >/dev/null; done  )

real    0m43.910s
user    0m40.178s
sys 0m4.119s

Boru versiyonunun daha büyük bir kurulum maliyeti var gibi görünüyor, ancak sonunda daha verimli.


@mikeserv Bu doğruydu. Daha fazla veri içeren bir karşılaştırma ölçütü ekledim.
PSkocik

2
echo foo >/dev/shm/1;cat /dev/shm/1 >/dev/nullher iki durumda da hızlı gibi görünüyordu ...
user23013

@ user23013 Bu mantıklı. Verimlilik için neden ya echo "$longstring"da <<<"$longstring"ayarlanacağını ya da kısa iplerle göremiyorum, verimlilik yine de önemli değil.
PSkocik

Benim durumumda (Ubuntu 14.04'te Intel quad core i7) cat <(echo foo) >/dev/nulldaha hızlı olması ilginç echo foo | cat >/dev/null.
pabouk

1
@Prem Evet, bu daha iyi bir yaklaşım olurdu, ama daha da iyisi, bu konuda hiç endişe etmemek ve iş için doğru aracı kullanmak değildir. Yorumlu metinlerin performansa göre ayarlanacağını düşünmek için hiçbir neden yoktur.
PSkocik
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.