Bash betiği; işlem hızının optimizasyonu


10

Bash betiklerini optimize etmek için genel kurallar olup olmadığını merak ediyordum.

  • Örneğin, döngü yazmak komut satırlarına göre daha uygundur , ancak sistem için daha hızlı işlem yapmak daha mı hızlıdır ? Misal:

    for i in a b c; do echo $i; done
    
    echo a
    echo b
    echo c
  • Bazen insanlar aynı sorun için farklı çözümler sunarlar. Örneğin sed, cut, awkve echoher bir dize basamak şerit edebiliyoruz. Daha az hane koduna sahip olduğunu söyleyebilir misiniz, daha hızlı kullanırsanız:

    1. aynı komut, ör.

      STRING=abc.def
      echo ${STRING} | sed 's/.def//g'
      echo ${STRING} | sed '$s/....$//'
    2. farklı komutlar, ör.

      STRING=abc.def
      echo ${STRING} | cut -d . -f 1
      echo ${STRING} | sed 's/.def//g'

2
Çoğu durumda hızda okunabilirliği tercih ederim.
Bernhard

1
a) Evet, for döngüsü kullanmanın bir yükü vardır, ancak önemli değildir b) harici komutları en aza indirmeye çalışın ve sadece bash içindeki şeyleri değiştirin. Kabuk betiğinizi optimize etmeniz gerekiyorsa, yanlış bir şey yapıyorsunuz ve daha iyi profiler desteğiyle bir dil kullanmayı düşünmelisiniz.
Ulrich Dangel

Düzenli ifadeler genellikle diğer seçeneklerden daha az verimli performanstır, bu yüzden bir şey olmadan (örneğin, kesilmiş) bir şey yapmanın bir yolunu görürseniz, bunu kullanın. Tabii ki olabilir okuma yeteneği düzenli ifadeler ile sınırlıdır eğer okunabilirliği etkileyebilir;)
goldilocks

Yanıtlar:


8

Kabuklar teslim ettikleri kodun yeniden düzenlenmesini sağlamazlar, sadece bir satır birbiri ardına yorumlanırlar (başka bir şey komut yorumlayıcısında fazla bir anlam ifade etmez). Kabuk tarafından harcanan zamanın çoğu, sözlü analiz / ayrıştırma / başlatılan programları başlatır.

Basit işlemler için (sorunun sonundaki örneklerde dizeleri çalkalayanlar gibi) programları yüklemek için zamanın herhangi bir minik hız farkını değiştirmemesi şaşırtıcı olurdu.

Hikayenin ahlakı, gerçekten daha fazla hıza ihtiyacınız varsa, Perl veya Python gibi (yarı) derlenmiş bir dille daha iyi durumda olmanızdır, bu da başlamak için daha hızlıdır ve doğrudan bahsedilen işlemlerin çoğunu yazabilirsiniz. ve harici programlara çağrı yapmak zorunda kalmazsınız ve işin çoğunu yapmak için harici programları çağırmak veya optimize edilmiş C (veya herhangi bir şekilde) modüllere çağrı yapmak seçeneğine sahiptir. Fedora'da "sistem yönetim şekeri" nin (GUI'ler, esasen) Python'da yazılmasının nedeni budur: Çok fazla çaba göstermeyen, bu tür uygulamalar için yeterince hızlı olan güzel bir GUI ekleyebilir, sistem çağrılarına doğrudan erişebilir. Bu yeterli hızda değilse, C ++ veya C'yi alın.

Ama yok sen sürece, oraya gitmek ispat performans kazancı esneklik kaybı ve geliştirme süresi değerinde olduğunu. Kabuk betikleri okumak için çok kötü değil, ama Ultrix I'i yüklemek için kullanılan bazı betikleri hatırladığımda titremeye başladım. Ben vazgeçtim, çok fazla "kabuk script optimizasyonu" uygulanmıştı.


1
+1 ama bir çok insan , kayıp değil, python veya perl'e karşı bir şey kullanarak esneklik ve geliştirme süresinde bir kazanımın daha olası olduğunu savunuyor . Sadece gerekliyse bir kabuk komut dosyası kullanın ya da ne yaptığınız kabuk belirli komutları bol miktarda içerir söyleyebilirim.
goldilocks

22

Optimizasyonun ilk kuralı: optimize etmeyin . Önce test edin. Testler programınızın çok yavaş olduğunu gösteriyorsa, olası optimizasyonları arayın.

Emin olmanın tek yolu, kullanım durumunuz için kıyaslama yapmaktır. Bazı genel kurallar vardır, ancak bunlar yalnızca tipik uygulamalardaki tipik veri hacimleri için geçerlidir.

Herhangi bir özel durumda geçerli olabilecek veya olmayabilecek bazı genel kurallar:

  • Kabuktaki dahili işlemler için ATT ksh en hızlısıdır. Çok sayıda dize düzenleme yaparsanız, ATT ksh kullanın. Dash ikinci sırada gelir; bash, pdksh ve zsh geride kalıyor.
  • Her seferinde çok kısa bir görev yapmak için sık sık bir kabuk çağırmanız gerekiyorsa, kısa başlatma süresi nedeniyle çizgi kazanır.
  • Harici bir işlem başlatmak zaman alır, bu nedenle karmaşık parçalara sahip bir boru hattına sahip olmak, bir döngüdeki bir boru hattından daha hızlıdır.
  • echo $foodaha yavaştır echo "$foo", çünkü çift tırnak işaretleri olmadan $fookelimelere ayrılır ve her kelimeyi bir dosya adı joker karakteri deseni olarak yorumlar. Daha da önemlisi, bölünme ve zonklama davranışı nadiren istenir. Bu nedenle, değişken ikamelerin ve komut ikamelerinin etrafına her zaman çift tırnak koymayı unutmayın: "$foo", "$(foo)".
  • Özel araçlar genel amaçlı araçlar kazanma eğilimindedir. Örneğin, benzeyen cutveya headbenzetilebilen araçlar sed, ancak seddaha yavaş ve awkdaha yavaş olacaktır. Kabuk dizesi işleme yavaştır, ancak kısa dizeler için harici bir program çağırmayı büyük ölçüde yener.
  • Perl, Python ve Ruby gibi daha gelişmiş diller genellikle daha hızlı algoritmalar yazmanıza izin verir, ancak önemli ölçüde daha yüksek bir başlatma süresine sahiptirler, bu nedenle sadece büyük miktarlardaki veriler için performans için değerlidirler.
  • En azından Linux'ta, borular geçici dosyalardan daha hızlı olma eğilimindedir.
  • Kabuk komut dosyası kullanımının çoğu kullanımı G / Ç'ye bağlı işlemlerle ilgilidir, bu nedenle CPU tüketimi önemli değildir.

Kabuk komut dosyalarında performansın endişe kaynağı olması nadirdir. Yukarıdaki liste tamamen gösterge niteliğindedir; çoğu durumda “yavaş” yöntemleri kullanmak son derece iyidir, çünkü fark genellikle yüzde oranının bir kısmıdır.

Genellikle bir kabuk betiğinin amacı bir şeyi hızlı bir şekilde yapmaktır. Senaryoyu yazmak için fazladan dakika harcamalarını haklı çıkarmak için optimizasyondan çok kazanmanız gerekir.


2
pythonVe rubyen azından sistemimde başlamak kesinlikle ve daha yavaş olsa da perl, bashveya kadar hızlı başlar ksh. GNU awk, özellikle utf-8 yerel ayarlarında GNU sed'den önemli ölçüde yavaştır, ancak tüm awks ve tüm seds için geçerli değildir. ksh93> tire> pdksh> zsh> bash her zaman bu kadar net kesilmez. Bazı mermiler bazı şeylerde diğerlerinden daha iyidir ve kazanan her zaman aynı değildir.
Stéphane Chazelas

2
Re "çok şey kazanmak zorunda ..." : "siz" kullanıcı tabanını içeriyorsa, true. Popüler Linux paketlerindeki kabuk komut dosyalarıyla, kullanıcılar genellikle aceleci programcıya göre birkaç büyüklükte daha fazla sipariş toplarlar.
agc

2

Kabuk komut dosyası yorumlayıcısının bazı performans özelliklerini göstermek için yukarıdaki globbing örneğimizde burada genişleyeceğiz. 30.000 dosyanın her biri için bir işlemin üretildiği bu örnek için bashve dashyorumlayıcıları karşılaştırarak, tire işleminin wcyaklaşık iki kat daha hızlı işlem yapabileceğini gösterir.bash

bash-4.2$ time dash -c 'for i in *; do wc -l "$i"; done>/dev/null'
real    0m1.238s
user    0m0.309s
sys     0m0.815s


bash-4.2$ time bash -c 'for i in *; do wc -l "$i"; done>/dev/null'
real    0m1.422s
user    0m0.349s
sys     0m0.940s

wcİşlemleri başlatmayarak temel döngü hızını karşılaştırmak, çizgi döngüsünün yaklaşık 6 kat daha hızlı olduğunu gösterir!

$ time bash -c 'for i in *; do echo "$i">/dev/null; done'
real    0m1.715s
user    0m1.459s
sys     0m0.252s



$ time dash -c 'for i in *; do echo "$i">/dev/null; done'
real    0m0.375s
user    0m0.169s
sys     0m0.203s

Döngü, her iki kabukta da daha önce gösterildiği gibi nispeten yavaştır, bu nedenle ölçeklenebilirlik için daha fonksiyonel teknikler denemeli ve kullanmalıyız, böylece derleme işlemlerinde yineleme yapılır.

$ time find -type f -print0 | wc -l --files0-from=- | tail -n1
    30000 total
real    0m0.299s
user    0m0.072s
sys     0m0.221s

Yukarıdakiler en etkili çözümdür ve bir kişinin kabuk betiğinde mümkün olduğunca az yapması ve UNIX sisteminde bulunan zengin yardımcı program kümesindeki mevcut mantığı bağlamak için kullanmayı amaçladığı noktayı iyi göstermektedir.

Gönderen Çalıntı Ortak kabuk komut dosyası hataları Pádraig Brady tarafından.


1
Genel bir kural: dosya tanıtıcı işlemesi de maliyetlidir, bu nedenle sayılarını azaltın. for i in *; do wc -l "$i">/dev/null; doneDaha iyi yapmak yerine for i in *; do wc -l "$i"; done>/dev/null.
Manatwork

@manatwork ayrıca timecmd çıktısını sıfırlayacak
Rahul Patil

@manatwork İyi ... şimdi Lütfen beni çağırmadan çıktısını ver wc -l, kontrol ben çıktısını güncelledim kontrol
Rahul Patil

Önceki ölçümler daha küçük bir dizinde yapıldı. Şimdi 30000 dosya ile bir tane oluşturdum ve testleri tekrarladım: pastebin.com/pCV6QKp2
manatwork

Bu kriterler her kabuğun farklı başlangıç ​​zamanlarına izin vermiyor. Her kabuğun içinden yapılan karşılaştırmalar daha iyi olurdu.
agc
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.