Erlang 21 - 3. Common Caveats

3 आम कैविट्स




erlang

3 आम कैविट्स

यह खंड प्रदर्शन के दृष्टिकोण से ही नहीं, बल्कि देखने के लिए कुछ मॉड्यूल और BIF को सूचीबद्ध करता है।

3.1 टाइमर मॉड्यूल

erlang:send_after/3 का उपयोग करके टाइमर बनाना erlang:send_after/3 और erlang:start_timer/3 , STDLIB में timer मॉड्यूल द्वारा प्रदान की गई टाइमर का उपयोग करने की तुलना में बहुत अधिक कुशल है। timer मॉड्यूल timer का प्रबंधन करने के लिए एक अलग प्रक्रिया का उपयोग करता है। यदि कई प्रक्रियाएँ टाइमर को रद्द कर देती हैं और रद्द कर देती हैं तो यह प्रक्रिया आसानी से ओवरलोड हो सकती है (विशेषकर एसएमपी एमुलेटर का उपयोग करते समय)।

timer मॉड्यूल में कार्य जो टाइमर (जैसे timer:tc/3 या timer:sleep/1 ) का प्रबंधन नहीं करते हैं, टाइमर-सर्वर प्रक्रिया को कॉल नहीं करते हैं और इसलिए हानिरहित हैं।

३.२ सूची_तो_तोम / १

परमाणु कचरा-एकत्र नहीं होते हैं। एक बार एक परमाणु बनाया जाता है, तो इसे कभी नहीं हटाया जाता है। एमुलेटर समाप्त हो जाता है यदि परमाणुओं की संख्या की सीमा (डिफ़ॉल्ट रूप से 1,048,576) तक पहुंच जाती है।

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

list_to_atom/1 का उपयोग एक परमाणु बनाने के लिए किया जाता है जिसे apply/3 करने के apply/3 पास किया जाता है apply/3 निम्नानुसार है, काफी महंगा है और समय-महत्वपूर्ण कोड में अनुशंसित नहीं है:

apply(list_to_atom("some_prefix"++Var), foo, Args)

३.३ लंबाई / १

किसी सूची की लंबाई की गणना करने का समय सूची की लंबाई के समानुपाती होता है, जैसा कि tuple_size/1 , byte_size/1 और bit_size/1 , जो सभी निरंतर समय में निष्पादित होते हैं।

आम तौर पर, length/1 की गति के बारे में चिंता करने की कोई आवश्यकता नहीं है, क्योंकि यह कुशलता से सी में लागू किया जाता है। समय-महत्वपूर्ण कोड में, आप इससे बचना चाह सकते हैं यदि इनपुट सूची संभावित रूप से बहुत लंबी हो सकती है।

length/1 कुछ उपयोगों को मिलान करके बदला जा सकता है। उदाहरण के लिए, निम्न कोड:

foo(L) when length(L) >= 3 ->
    ...

के लिए फिर से लिखा जा सकता है:

foo([_,_,_|_]=L) ->
   ...

एक मामूली अंतर यह है कि length(L) विफल रहती है यदि L एक अनुचित सूची है, जबकि दूसरे कोड के टुकड़े में पैटर्न एक अनुचित सूची को स्वीकार करता है।

३.४ सेटेलमेंट / ३

setelement/3 उस setelement/3 कॉपी करता है जिसे वह संशोधित करता है। इसलिए, setelement/3 का उपयोग करके एक लूप में एक टपल को अपडेट करना हर बार टपल की एक नई प्रति बनाता है।

नियम का एक अपवाद है कि ट्यूपल की नकल की जाती है। यदि कंपाइलर स्पष्ट रूप से देख सकता है कि setelement/3 को विनाशकारी रूप से अपडेट कर रहा है तो वही परिणाम देगा जैसे कि setelement/3 को कॉपी किया गया था, setelement/3 कॉल को एक विशेष विनाशकारी setelement निर्देश के साथ बदल दिया जाता है। निम्नलिखित कोड अनुक्रम में, पहला setelement/3 कॉल टपल को कॉपी करता है और नौवें तत्व को संशोधित करता है:

multiple_setelement(T0) ->
    T1 = setelement(9, T0, bar),
    T2 = setelement(7, T1, foobar),
    setelement(5, T2, new_value).

दो निम्नलिखित setelement/3 कॉल जगह में ट्यूपल को संशोधित करते हैं।

ऑप्टिमाइज़ेशन लागू होने के लिए, सभी अनुसरण करने की शर्तें सही होनी चाहिए:

  • सूचकांक पूर्णांक शाब्दिक होने चाहिए, न कि चर या भाव।
  • सूचकांक को अवरोही क्रम में दिया जाना चाहिए।
  • कॉल setelement/3 बीच किसी अन्य फ़ंक्शन के लिए कोई कॉल नहीं होनी चाहिए।
  • एक setelement/3 कॉल से लौटा हुआ टपल केवल बाद के कॉल में setelement/3 में उपयोग किया जाना चाहिए।

यदि कोड को multiple_setelement/1 उदाहरण के रूप में संरचित नहीं किया जा सकता है, तो बड़े ट्यूपल में कई तत्वों को संशोधित करने का सबसे अच्छा तरीका है कि एक सूची में ट्यूपल को परिवर्तित करें, सूची को संशोधित करें, और इसे वापस ट्यूपल में परिवर्तित करें।

3.5 आकार / 1

size/1 टुपल्स और बायनेरिज़ दोनों के लिए आकार देता है।

BIFs tuple_size/1 और byte_size/1 का उपयोग करने से कंपाइलर और रनटाइम सिस्टम को ऑप्टिमाइज़ेशन के अधिक अवसर मिलते हैं। एक और लाभ यह है कि बीआईएफ डायलर को अधिक प्रकार की जानकारी देते हैं।

3.6 विभाजित_बिन / 2

आमतौर पर split_binary/2 फ़ंक्शन को कॉल करने के बजाय मिलान का उपयोग करके एक बाइनरी को विभाजित करना अधिक कुशल है। इसके अलावा, बिट सिंटैक्स मिलान और split_binary/2 को मिलाने से बिट सिंटैक्स मिलान की कुछ अनुकूलन को रोका जा सकता है।

करना

<<Bin1:Num/binary,Bin2/binary>> = Bin,

ऐसा न करें

{Bin1,Bin2} = split_binary(Bin, Num)

3.7 ऑपरेटर "-"

" -- " ऑपरेटर के पास अपने ऑपरेंड की लंबाई के उत्पाद के लिए आनुपातिक जटिलता होती है। इसका मतलब है कि ऑपरेटर बहुत धीमा है अगर उसके दोनों ऑपरेंड लंबी सूची हैं:

ऐसा न करें

HugeList1 -- HugeList2

इसके बजाय ordsets में ordsets मॉड्यूल का उपयोग करें:

करना

HugeSet1 = ordsets:from_list(HugeList1),
HugeSet2 = ordsets:from_list(HugeList2),
ordsets:subtract(HugeSet1, HugeSet2)

जाहिर है, यदि सूची का मूल क्रम महत्वपूर्ण है तो वह कोड काम नहीं करता है। यदि सूची का क्रम संरक्षित होना चाहिए, तो निम्नानुसार करें:

करना

Set = gb_sets:from_list(HugeList2),
[E || E <- HugeList1, not gb_sets:is_element(E, Set)]
ध्यान दें

यह कोड " -- " से अलग व्यवहार करता है यदि सूचियों में डुप्लिकेट तत्व होते हैं (HugeList2 में एक तत्व की घटना HugeList1 में सभी घटनाओं को हटा देती है।)

साथ ही, यह कोड " == " ऑपरेटर का उपयोग करते हुए सूचियों के तत्वों की तुलना करता है, जबकि " -- " " =:= " ऑपरेटर का उपयोग करता है। यदि वह अंतर महत्वपूर्ण है, तो sets gb_sets बजाय उपयोग किए जा सकते हैं, लेकिन sets:from_list/1 gb_sets:from_list/1 की तुलना में बहुत धीमा है gb_sets:from_list/1 लंबी सूची के लिए।

किसी सूची से किसी तत्व को हटाने के लिए " -- " ऑपरेटर का उपयोग करना प्रदर्शन समस्या नहीं है:

ठीक

HugeList1 -- [Element]