स्क्रिप्ट चलाने का सबसे तेज़ तरीका क्या है?


22

मैं सोच रहा था कि स्क्रिप्ट चलाने का सबसे तेज़ तरीका क्या है, मैं पढ़ रहा हूं कि टर्मिनल पर स्क्रिप्ट के आउटपुट को दिखाने के बीच गति में अंतर है, इसे किसी फ़ाइल या शायद पर पुनर्निर्देशित करना /dev/null

इसलिए यदि आउटपुट महत्वपूर्ण नहीं है, तो स्क्रिप्ट को तेजी से काम करने का सबसे तेज़ तरीका क्या है, भले ही यह न्यूनतम हो।

bash ./myscript.sh 
-or-
bash ./myscript.sh > myfile.log
-or-
bash ./myscript.sh > /dev/null


"रेगुलर फ़ाइल में रीडायरेक्टिंग" और "रीडायरेक्टिंग टू / देव /
न्यूल

जवाबों:


31

इन दिनों टर्मिनलों की तुलना में वे धीमी गति से होते थे, मुख्यतः क्योंकि ग्राफिक्स कार्ड 2 डी त्वरण के बारे में परवाह नहीं करते थे। तो वास्तव में, टर्मिनल पर मुद्रण एक स्क्रिप्ट को धीमा कर सकता है, खासकर जब स्क्रॉलिंग शामिल हो।

नतीजतन ./script.shकी तुलना में धीमी है ./script.sh >script.log, जो बदले में की तुलना में धीमी है/script.sh >/dev/null , क्योंकि बाद में कम काम शामिल है। हालाँकि यह किसी भी व्यावहारिक उद्देश्य के लिए पर्याप्त अंतर बनाता है या नहीं यह इस बात पर निर्भर करता है कि आपकी स्क्रिप्ट कितनी आउटपुट और कितनी तेजी से उत्पन्न होती है। यदि आपकी स्क्रिप्ट 3 पंक्तियाँ लिखती है और बाहर निकलती है, या यदि यह हर कुछ घंटों में 3 पृष्ठ प्रिंट करती है, तो आपको शायद पुनर्निर्देशन से परेशान होने की आवश्यकता नहीं है।

संपादित करें: कुछ त्वरित (और पूरी तरह से टूटे हुए) मानक:

  • लिनक्स कंसोल में, 240x75:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    3m52.053s
    user    0m0.617s
    sys     3m51.442s
  • एक में xterm, 260x78:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
  • सैमसंग SSD 850 PRO 512GB डिस्क पर एक फ़ाइल पर पुनर्निर्देशित करें:

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >file)
     real    0m0.532s
     user    0m0.464s
     sys     0m0.068s
  • पुनर्निर्देशित करें /dev/null:

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >/dev/null)
     real    0m0.448s
     user    0m0.432s
     sys     0m0.016s

6
@Kingofkech यह 200 रेखाओं / सेकंड से कम है। इससे बहुत फर्क नहीं पड़ेगा। (तुलना के लिए, timeout 1 yes "This is a looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"मेरी MBP पर एक सेकंड में 100000+ लाइनें प्रिंट करता है।)
muru

4
@Kingofkech यदि यह एक स्क्रिप्ट है, तो एक फ़ाइल को संपादित करें और उस लाइन पर टिप्पणी करें जो अनावश्यक आउटपुट प्रिंट करता है। आप बहुत कुछ हासिल करेंगे, खासकर अगर यह एक बाहरी कमांड है (शेल निर्मित नहीं है) 3 मिलियन बार निष्पादित किया गया ...
जिमिज

2
"हुआ करते थे" की एक संकीर्ण व्याख्या के लिए। एक vt220 टर्मिनल आज के टर्मिनल एमुलेटर की तुलना में धीमा है। इसके अलावा, SUN स्पार्क कार्यस्थानों (मैंने जिन लोगों का उपयोग किया था) में वास्तव में धीमा कंसोल था, इसलिए किसी बड़े प्रोजेक्ट को संकलित करते समय आउटपुट को एक फ़ाइल में रीडायरेक्ट किया जाता था।
Kusalananda

1
@ कुसलानंद यह सच है, xterm30 साल पहले के एचपी अपोलो xtermsपर 20 साल पहले के एचपी-यूएक्स की तुलना में क्रॉल किया जाता था। हालांकि, 15 साल पहले के एक Matrox वीडियो कार्ड के साथ एक लिनक्स कंसोल 20 साल पहले S3 कार्ड के साथ एक ही लिनक्स कंसोल की तुलना में धीमा था। और आधुनिक कार्ड पर उच्च-रिज़ॉल्यूशन फ्रेम बफर के साथ एक लिनक्स कंसोल बस बेकार है। :)
सातु कटुरा

6
@Kingofkech यह लगभग 2400 बीपीएस है। हम में से कुछ वास्तव में उन गति के साथ वर्षों तक रहते थे। :)
सातु कटुरा

14

मैं सहज रूप से सतो कातसुरा के उत्तर से सहमत होता; यह समझ में आता है। हालांकि, यह परीक्षण करने के लिए काफी आसान है।

मैंने स्क्रीन पर एक लाख लाइनें लिखने, एक फ़ाइल पर लिखने (एपेंडिंग) का परीक्षण किया, और इसके लिए रीडायरेक्ट किया /dev/null। मैंने इनमें से प्रत्येक का परीक्षण किया, फिर पाँच प्रतिकृति की। ये वो कमांड हैं जिनका मैंने इस्तेमाल किया।

$ time (for i in {1..1000000}; do echo foo; done)
$ time (for i in {1..1000000}; do echo foo; done > /tmp/file.log) 
$ time (for i in {1..1000000}; do echo foo; done > /dev/null)

फिर मैंने नीचे कुल बार प्लॉट किया।

समय बनाम उत्पादन की साजिश

जैसा कि आप देख सकते हैं, Satō Katsura के अनुमान सही थे। सात्सु कटसुरा के उत्तर के अनुसार, मुझे यह भी संदेह है कि सीमित कारक आउटपुट होगा, इसलिए यह संभावना नहीं है कि आउटपुट की पसंद का स्क्रिप्ट की समग्र गति पर पर्याप्त प्रभाव पड़ेगा।

एफडब्ल्यूआईडब्ल्यू, मेरे मूल उत्तर में अलग कोड था, जिसमें लूप के अंदर फ़ाइल को जोड़ना और /dev/nullरीडायरेक्ट करना था

$ rm /tmp/file.log; touch /tmp/file.log; time (for i in {1..1000000}; do echo foo >> /tmp/file.log; done) 
$ time (for i in {1..1000000}; do echo foo > /dev/null; done)

जैसा कि जॉन कुगेलमैन टिप्पणियों में बताते हैं, यह बहुत अधिक उपरि जोड़ता है। जैसा कि प्रश्न खड़ा है, यह वास्तव में इसे जांचने का सही तरीका नहीं है, लेकिन मैं इसे यहां छोड़ दूंगा क्योंकि यह स्क्रिप्ट के भीतर से किसी फ़ाइल को बार-बार खोलने की लागत को स्पष्ट रूप से दिखाता है।

समय बनाम उत्पादन की साजिश

इस मामले में, परिणाम उलट हैं।


FWIW मैंने अपने उत्तर में एक त्वरित बेंचमार्क जोड़ा। विशेष रूप से, लिनक्स कंसोल एक की तुलना में 200 गुना धीमा है xterm, जो बदले में ~ 3 गुना धीमा है /dev/null
सातु कटुरा

आपको कुछ दर सीमित करने के साथ भी परीक्षण करना चाहिए। ओपी का आउटपुट लगभग 200 लाइनें / s है।
मूरू

@muru क्या आपका मतलब है कि एक लाइन प्रिंट करें, 1/200 सेकंड प्रतीक्षा करें, फिर दोहराएं? मैं कोशिश कर सकता हूं, लेकिन मुझे लगता है कि यह समान परिणाम होंगे, लेकिन शोर को दूर करने के लिए सिग्नल के लिए बस अधिक समय लगेगा। हालांकि शायद मैं विश्लेषण से पहले प्रतीक्षा समय घटा सकता हूं।
स्पार्कहॉक

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

3

स्क्रिप्ट को गति देने का एक और तरीका एक तेज शेल दुभाषिया का उपयोग करना है। POSIX व्यस्त लूप की गति की तुलना करें , bash v4.4 , ksh v93u + 20120801 , और dash v0.5.8 के तहत चलाएं

  1. bash:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | bash -s > /dev/null

    आउटपुट:

    real    0m25.146s
    user    0m24.814s
    sys 0m0.272s
  2. ksh:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | ksh -s > /dev/null

    आउटपुट:

    real    0m11.767s
    user    0m11.615s
    sys 0m0.010s
  3. dash:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | dash -s > /dev/null

    आउटपुट:

    real    0m4.886s
    user    0m4.690s
    sys 0m0.184s

एक सबसेट में आदेशों की bashऔर kshकर रहे हैं backwardly संगत में आदेश सभी के लिए dash। एक bashस्क्रिप्ट जो केवल उस सबसेट में कमांड का उपयोग करती है, उसके साथ काम करना चाहिए dash

कुछ bashस्क्रिप्ट जो नई सुविधाओं का उपयोग करती हैं, उन्हें दूसरे दुभाषिया में परिवर्तित किया जा सकता है। यदि bashस्क्रिप्ट नई सुविधाओं पर बहुत अधिक निर्भर करती है, तो वह परेशान होने के लायक नहीं हो सकती है - कुछ नई bashसुविधाएँ सुधार रही हैं जो कोड को आसान और अधिक कुशल दोनों हैं , ( bashआमतौर पर धीमी होने के बावजूद ), ताकि dashसमकक्ष, (जिसमें भाग लेना शामिल हो सके) कई अन्य आदेश), धीमा होगा।

जब संदेह में, एक परीक्षण चलाने ...


इसलिए मेरी बैश स्क्रिप्ट को फास्ट करने के लिए, मुझे उन्हें बैश या ksh में फिर से लिखना होगा?
किंगोफकेच

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