बैश लिपि; प्रसंस्करण की गति का अनुकूलन


10

मैं सोच रहा था कि क्या बैश स्क्रिप्ट के अनुकूलन के लिए सामान्य दिशानिर्देश हैं।

  • उदाहरण के लिए, कमांड की लाइनों की तुलना में लूप लिखना अधिक सुविधाजनक है, लेकिन क्या सिस्टम के लिए प्रोसेस करना भी तेज है? उदाहरण:

    for i in a b c; do echo $i; done
    
    echo a
    echo b
    echo c
    
  • कभी-कभी लोग एक ही समस्या के लिए अलग-अलग समाधान प्रस्तुत करते हैं। उदाहरण के लिए, sed, cut, awk, और echoसभी एक स्ट्रिंग से अंक पट्टी में सक्षम हैं। मैं सोच रहा था कि क्या आप कह सकते हैं कि जितना कम अंकों का कोड होगा, उतना ही तेज होगा यदि आप उपयोग करते हैं:

    1. एक ही आदेश, उदाहरण के लिए;

      STRING=abc.def
      echo ${STRING} | sed 's/.def//g'
      echo ${STRING} | sed '$s/....$//'
      
    2. विभिन्न आज्ञाओं, जैसे

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

2
ज्यादातर मामलों में मैं गति से अधिक पठनीयता पसंद करूंगा।
बर्नहार्ड

1
क) हाँ लूप के लिए उपयोग करने में एक ओवरहेड है, लेकिन यह कोई फर्क नहीं पड़ता है) बाहरी आदेशों को कम करने और बस बैश के भीतर से चीजों को बदलने की कोशिश करें। और अगर आपको अपनी शेल स्क्रिप्ट को ऑप्टिमाइज़ करना है तो आप कुछ गलत कर रहे हैं और बेहतर प्रोफाइलर सपोर्ट वाली भाषा का उपयोग करने पर विचार करना चाहिए।
उलरिच डैंगेल

नियमित अभिव्यक्तियाँ आम तौर पर किसी अन्य विकल्प की तुलना में कम कुशल प्रदर्शन होती हैं, इसलिए यदि आप एक के बिना कुछ करने का एक तरीका देखते हैं (जैसे, कट), तो इसका उपयोग करें। बेशक, यह पठनीयता को प्रभावित कर सकता है यदि आपकी पढ़ने की क्षमता नियमित अभिव्यक्तियों तक सीमित है;)
गोल्डीलॉक्स

जवाबों:


8

शेल उनके द्वारा सौंपे गए कोड का कोई पुनर्गठन नहीं करते हैं, यह सिर्फ एक पंक्ति के बाद दूसरे की व्याख्या की जाती है (कमांड इंटरप्रेटर में और कुछ नहीं करता है)। शेल द्वारा बिताया गया अधिकांश समय लेक्सिकल विश्लेषण / पार्सिंग / लॉन्चिंग कार्यक्रमों को जाता है।

सरल ऑपरेशनों के लिए (जैसे प्रश्न के अंत में उदाहरणों में स्ट्रिंग्स को गूंथते हुए) यदि प्रोग्राम को लोड करने का समय किसी भी मामूली गति के अंतर को नहीं बदलता है तो मुझे आश्चर्य होगा।

कहानी की नैतिकता यह है कि यदि आपको वास्तव में अधिक गति की आवश्यकता है, तो आप पर्ल या पाइथन जैसी एक (अर्ध) संकलित भाषा के साथ बेहतर हैं, जिसे शुरू करने के लिए चलाने के लिए तेज़ है, जिसमें आप सीधे उल्लिखित कई ऑपरेशन लिख सकते हैं और बाहरी कार्यक्रमों को कॉल करने की आवश्यकता नहीं है, और बाहरी कार्यक्रमों को लागू करने या अनुकूलित सी (या जो भी) मॉड्यूल को काम करने के लिए कॉल करने का विकल्प है। यही कारण है कि फेडोरा में "सिस्टम एडमिनिस्ट्रेशन शुगर" (GUIs, अनिवार्य रूप से) पायथन में लिखे गए हैं: बहुत अच्छे प्रयास के साथ एक अच्छा GUI नहीं जोड़ सकते हैं, ऐसे अनुप्रयोगों के लिए पर्याप्त तेज़, सिस्टम कॉल तक सीधी पहुंच है। यदि वह पर्याप्त गति नहीं है, तो C ++ या C को पकड़ो।

लेकिन वहां मत जाओ, जब तक आप यह साबित नहीं कर सकते कि प्रदर्शन लाभ लचीलापन और विकास के समय में नुकसान के लायक है। शेल स्क्रिप्ट पढ़ने के लिए बहुत खराब नहीं हैं, लेकिन जब मुझे याद आता है कि मुझे कुछ ऐसे स्क्रिप्ट याद हैं जो अल्ट्रिक्स को स्थापित करने के लिए उपयोग किए जाते हैं तो मैंने एक बार समझने की कोशिश की। मैंने छोड़ दिया, बहुत अधिक "शेल स्क्रिप्ट अनुकूलन" लागू किया गया था।


1
+1 लेकिन बहुत से लोग तर्क देंगे कि अजगर या पर्ल बनाम शेल जैसी किसी चीज़ का उपयोग करके लचीलेपन और विकास के समय में लाभ होने की संभावना है , नुकसान नहीं। मैं कहूंगा कि केवल शेल स्क्रिप्ट का उपयोग करें यदि यह आवश्यक है, या आप जो कर रहे हैं, उसमें शेल विशिष्ट कमांडों की प्रचुर मात्रा शामिल है।
गोल्डीलॉक्स

22

अनुकूलन का पहला नियम है: अनुकूलन न करें । पहले परीक्षण करें। यदि परीक्षण दिखाते हैं कि आपका कार्यक्रम बहुत धीमा है, तो संभावित अनुकूलन देखें।

सुनिश्चित करने का एकमात्र तरीका आपके उपयोग के मामले के लिए बेंचमार्क है। कुछ सामान्य नियम हैं, लेकिन वे केवल विशिष्ट अनुप्रयोगों में डेटा के विशिष्ट संस्करणों के लिए लागू होते हैं।

कुछ सामान्य नियम जो किसी विशेष परिस्थिति में सच हो सकते हैं या नहीं भी हो सकते हैं:

  • शेल में आंतरिक प्रसंस्करण के लिए, ATT ksh सबसे तेज है। यदि आप बहुत सारे स्ट्रिंग जोड़तोड़ करते हैं, तो एटीटी ksh का उपयोग करें। डैश दूसरा आता है; bash, pdksh और zsh पिछड़ जाते हैं।
  • यदि आपको प्रत्येक बार बहुत कम कार्य करने के लिए किसी शेल को बार-बार इनवॉइस करने की आवश्यकता होती है, तो इसके कम स्टार्टअप समय के कारण डैश जीत जाता है।
  • बाहरी प्रक्रिया शुरू करने में समय लगता है, इसलिए एक लूप में एक पाइपलाइन की तुलना में जटिल टुकड़ों के साथ एक पाइप लाइन होना तेजी से होता है।
  • echo $fooकी तुलना में धीमी है echo "$foo", क्योंकि कोई दोहरे उद्धरण के साथ, यह $fooशब्दों में विभाजित होता है और प्रत्येक शब्द को फ़ाइल नाम वाइल्डकार्ड पैटर्न के रूप में व्याख्या करता है। इससे भी महत्वपूर्ण बात यह है कि विभाजन और ग्लोबिंग व्यवहार शायद ही कभी वांछित है। तो चर प्रतिस्थापन और आदेश प्रतिस्थापन के आसपास हमेशा डाल दोहरे उद्धरण चिह्नों का ध्यान रखें: "$foo", "$(foo)"
  • समर्पित उपकरण सामान्य-उद्देश्य वाले उपकरणों पर जीत हासिल करते हैं। उदाहरण के लिए, जैसे उपकरण cutया के headसाथ अनुकरण किया जा सकता है sed, लेकिन sedधीमी और होगाawk होगी धीमी भी होगी। शेल स्ट्रिंग प्रसंस्करण धीमा है, लेकिन छोटे तारों के लिए यह मोटे तौर पर बाहरी कार्यक्रम को बुलाता है।
  • अधिक उन्नत भाषाएं जैसे पर्ल, पायथन, और रूबी अक्सर आपको तेज एल्गोरिदम लिखने देती हैं, लेकिन उनके पास स्टार्टअप का समय काफी अधिक होता है, इसलिए वे केवल बड़ी मात्रा में डेटा के प्रदर्शन के लायक हैं।
  • कम से कम लिनक्स पर, पाइप अस्थायी फ़ाइलों की तुलना में अधिक तेज़ होते हैं।
  • शेल स्क्रिप्टिंग के अधिकांश उपयोग I / O- बाउंड प्रक्रियाओं के आसपास हैं, इसलिए CPU खपत कोई फर्क नहीं पड़ता।

यह दुर्लभ है कि शेल स्क्रिप्ट में प्रदर्शन एक चिंता का विषय है।उपरोक्त सूची पूरी तरह से सांकेतिक है; अधिकांश मामलों में "धीमी" विधियों का उपयोग करना पूरी तरह से ठीक है क्योंकि अंतर अक्सर प्रतिशत का एक अंश होता है।

आमतौर पर शेल स्क्रिप्ट की बात तेजी से कुछ करने के लिए होती है। स्क्रिप्ट लिखने में अतिरिक्त मिनट खर्च करने को सही ठहराने के लिए आपको अनुकूलन से बहुत कुछ हासिल करना होगा।


2
जबकि pythonऔर rubyनिश्चित रूप से शुरू करने के लिए धीमी है, कम से कम मेरे सिस्टम पर, perlके रूप में शुरू करने के लिए bashया के रूप में जल्दी है ksh। GNU awk विशेष रूप से utf-8 स्थानों में GNU sed की तुलना में काफी धीमा है, लेकिन यह सभी awks और सभी seds के लिए सही नहीं है। ksh93> डैश> pdksh> zsh> बैश हमेशा की तरह स्पष्ट कटौती नहीं है। कुछ गोले दूसरों की तुलना में कुछ चीजों में बेहतर होते हैं, और विजेता हमेशा समान नहीं होता है।
स्टीफन चेजलस

2
पुन: "आपको बहुत कुछ हासिल करना है ..." : यदि "आप" में उपयोगकर्ताबेस शामिल है, तो यह सच है। लोकप्रिय लिनक्स पैकेजों में शेल स्क्रिप्ट के साथ, अक्सर उपयोगकर्ता सामूहिक रूप से जल्दबाजी में प्रोग्रामर की बचत से अधिक समय के परिमाण के कई आदेशों को बर्बाद कर देते हैं।
१०:१५ बजे

2

हम शेल स्क्रिप्ट दुभाषिया की कुछ प्रदर्शन विशेषताओं का वर्णन करने के लिए ऊपर हमारे ग्लोबिंग उदाहरण पर यहां विस्तार करेंगे। तुलना bashऔर dashइस उदाहरण है, जहां एक प्रक्रिया 30,000 फाइलें, शो है कि पानी का छींटा कांटा कर सकते हैं में से प्रत्येक के लिए पैदा की है के लिए दुभाषिए wcसे लगभग दुगनी तेजी से प्रक्रियाओं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प्रक्रियाओं को न करके , यह दर्शाता है कि डैश की लूपिंग लगभग 6 गुना तेज है!

$ 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

लूपिंग पहले के प्रदर्शन के रूप में या तो शेल में अपेक्षाकृत धीमी है, इसलिए स्केलेबिलिटी के लिए हमें और अधिक कार्यात्मक तकनीकों का उपयोग करना चाहिए ताकि संकलित प्रक्रियाओं में पुनरावृत्ति का प्रदर्शन किया जाए।

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

उपरोक्त अब तक सबसे कुशल समाधान है और इस बिंदु को अच्छी तरह से दिखाता है कि किसी को शेल स्क्रिप्ट में जितना संभव हो उतना कम करना चाहिए और इसका उपयोग यूनिक्स प्रणाली पर उपलब्ध उपयोगिताओं के समृद्ध सेट में उपलब्ध मौजूदा तर्क को जोड़ने के लिए करना चाहिए।

Pádraig ब्रैडी द्वारा आम खोल स्क्रिप्ट गलतियों से चोरी ।


1
एक सामान्य नियम: फ़ाइल डिस्क्रिप्टर हैंडलिंग भी लागत होती है, इसलिए उनकी गिनती कम करें। इसके बजाय for i in *; do wc -l "$i">/dev/null; doneबेहतर करो for i in *; do wc -l "$i"; done>/dev/null
मैनटवर्क

@manatwork यह timecmd के आउटपुट को भी शून्य कर देगा
राहुल पाटिल

@manatwork अच्छा ... अब कृपया मुझे बिना इनवॉइस के आउटपुट भी दें wc -l, चेक करें कि मैंने आपके आउटपुट को पोस्ट किया है
राहुल पाटिल

खैर, पिछले माप एक छोटी निर्देशिका पर किए गए थे। अब मैंने 30000 फाइलों के साथ एक बनाया और परीक्षणों को दोहराया: pastebin.com/pCV6QKp2
manatwork

वे बेंचमार्क प्रत्येक शेल के अलग-अलग शुरुआती समय के लिए अनुमति देने में विफल रहते हैं। प्रत्येक शेल के भीतर से किए गए बेंचमार्क बेहतर होंगे।
एजीसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.