Erlang 21 - 2. The Seven Myths of Erlang Performance

2 एर्लांग प्रदर्शन के सात मिथक




erlang

2 एर्लांग प्रदर्शन के सात मिथक

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

यह खंड मिथकों बन चुके पुराने सत्य (या अर्ध-सत्य) को मारने की कोशिश करता है।

२.१ मिथक: टेल-रिकर्सिव फ़ंक्शंस, रिकर्सिव फ़ंक्शंस की तुलना में बहुत तेज़ हैं

मिथक के अनुसार, पूंछ-पुनरावर्ती फ़ंक्शन का उपयोग करना जो सूची में कॉल के बाद रिवर्स में एक सूची बनाता है lists:reverse/1 एक शरीर-पुनरावर्ती फ़ंक्शन की तुलना में तेज है जो सूची को सही क्रम में बनाता है; कारण यह है कि शरीर-पुनरावर्ती कार्य पूंछ-पुनरावर्ती कार्यों की तुलना में अधिक स्मृति का उपयोग करते हैं।

यह R12B से पहले कुछ हद तक सही था। यह R7B से पहले और भी सच था। आज इतना नहीं। एक शरीर-पुनरावर्ती समारोह आम तौर पर पूंछ-पुनरावर्ती कार्य के रूप में स्मृति की समान मात्रा का उपयोग करता है। आमतौर पर यह अनुमान लगाना संभव नहीं है कि पूंछ-पुनरावर्ती या शरीर-पुनरावर्ती संस्करण तेज होगा या नहीं। इसलिए, उस संस्करण का उपयोग करें जो आपके कोड को क्लीनर बनाता है (संकेत: यह आमतौर पर शरीर-पुनरावर्ती संस्करण है)।

पूंछ और शरीर की पुनरावृत्ति के बारे में अधिक गहन चर्चा के लिए, देखें Erlang's Tail Recursion is Not a Silver Bullet

ध्यान दें

एक पूंछ-पुनरावर्ती फ़ंक्शन जिसे अंत में सूची को उलटने की आवश्यकता नहीं होती है, शरीर-पुनरावर्ती फ़ंक्शन की तुलना में तेज़ होता है, जैसा कि पूंछ-पुनरावर्ती कार्य हैं जो किसी भी शब्द का निर्माण नहीं करते हैं (उदाहरण के लिए, एक फ़ंक्शन जो सभी पूर्णांकों को गाया जाता है। एक सूचि)।

2.2 मिथक: ऑपरेटर "++" हमेशा खराब होता है

++ ऑपरेटर को कुछ हद तक अवांछनीय रूप से खराब प्रतिष्ठा मिली है। यह संभवतः निम्नलिखित जैसे कोड के साथ कुछ करना है, जो एक सूची को उलटने के लिए सबसे अक्षम तरीका है:

ऐसा न करें

naive_reverse([H|T]) ->
    naive_reverse(T)++[H];
naive_reverse([]) ->
    [].

चूंकि ++ ऑपरेटर अपने बाएं ऑपरेंड को कॉपी करता है, परिणाम बार-बार कॉपी किया जाता है, जिससे द्विघात जटिलता होती है।

लेकिन ++ का उपयोग निम्नानुसार बुरा नहीं है:

ठीक

naive_but_ok_reverse([H|T], Acc) ->
    naive_but_ok_reverse(T, [H]++Acc);
naive_but_ok_reverse([], Acc) ->
    Acc.

प्रत्येक सूची तत्व को केवल एक बार कॉपी किया जाता है। बढ़ते परिणाम Acc ++ ऑपरेटर के लिए सही ऑपरेंड है, और यह कॉपी नहीं किया गया है।

अनुभवी एरलांग प्रोग्रामर निम्नानुसार लिखेंगे:

करना

vanilla_reverse([H|T], Acc) ->
    vanilla_reverse(T, [H|Acc]);
vanilla_reverse([], Acc) ->
    Acc.

यह थोड़ा और अधिक कुशल है क्योंकि यहाँ आप केवल इसे कॉपी करने के लिए सूची तत्व का निर्माण नहीं करते हैं। (या यह अधिक प्रभावी होगा यदि कंपाइलर स्वचालित रूप से [H]++Acc को [H|Acc] को फिर से नहीं [H|Acc] ।)

2.3 मिथक: स्ट्रिंग्स स्लो हैं

अनुचित तरीके से किए जाने पर स्ट्रिंग हैंडलिंग धीमी हो सकती है। एर्लैंग में, आपको थोड़ा और सोचने की ज़रूरत है कि स्ट्रिंग्स का उपयोग कैसे किया जाता है और एक उचित प्रतिनिधित्व का चयन करें। यदि आप नियमित अभिव्यक्तियों का उपयोग करते हैं, तो अप्रचलित regexp मॉड्यूल के बजाय STDLIB में re मॉड्यूल का उपयोग करें।

2.4 मिथक: डाइट फ़ाइल की मरम्मत बहुत धीमी है

मरम्मत का समय अभी भी फ़ाइल में रिकॉर्ड की संख्या के लिए आनुपातिक है, लेकिन Dets की मरम्मत अतीत में बहुत धीमी हुआ करती थी। डेट्स को बड़े पैमाने पर फिर से लिखा गया है और बेहतर बनाया गया है।

2.5 मिथक: BEAM एक स्टैक-आधारित बाइट-कोड वर्चुअल मशीन है (और इसलिए धीमा)

BEAM एक रजिस्टर-आधारित वर्चुअल मशीन है। इसमें 1024 वर्चुअल रजिस्टर हैं जो अस्थायी मान रखने और कार्यों को कॉल करते समय तर्कों को पारित करने के लिए उपयोग किए जाते हैं। एक फ़ंक्शन कॉल को जीवित रहने की आवश्यकता वाले चर को स्टैक में सहेजा जाता है।

BEAM एक थ्रेडेड कोड दुभाषिया है। प्रत्येक निर्देश सीधे निष्पादन योग्य सी-कोड को इंगित करता है, जिससे अनुदेश बहुत तेजी से प्रेषित होता है।

2.6 मिथक: अपने प्रोग्राम को गति देने के लिए "_" का उपयोग करें जब एक चर का उपयोग नहीं किया जाता है

यह एक बार सच था, लेकिन R6B से BEAM संकलक देख सकता है कि एक चर का उपयोग नहीं किया गया है।

इसी प्रकार, स्रोत-कोड स्तर पर तुच्छ परिवर्तन जैसे कि case स्टेटमेंट को फ़ंक्शन के शीर्ष-स्तर पर खंडों में परिवर्तित करना शायद ही कभी उत्पन्न कोड पर कोई फर्क पड़ता है।

2.7 मिथक: एक एनआईएफ हमेशा आपके कार्यक्रम को गति देता है

एक तेजी से बनाने के लिए एक एनआईएफ के लिए इरलांग कोड को फिर से लिखना एक अंतिम उपाय के रूप में देखा जाना चाहिए। यह केवल खतरनाक होने की गारंटी है, लेकिन कार्यक्रम को गति देने की गारंटी नहीं है।

प्रत्येक NIF कॉल में बहुत अधिक काम degrade responsiveness of the VM हो जाएगी। बहुत कम काम करने का मतलब यह हो सकता है कि एनआईएफ में तेजी से प्रसंस्करण का लाभ एनआईएफ को कॉल करने और तर्कों की जांच के ओवरहेड द्वारा खाया जाता है।

Long-running NIFs लिखने से पहले Long-running NIFs बारे में पढ़ना सुनिश्चित करें।