Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

रूबिस्ट गाइड टू मेमोइज़ेशन

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

इस तकनीक को "संस्मरण" कहा जाता है। $ 10 कंप्यूटर-विज्ञान शब्द के बावजूद, इसका सीधा सा मतलब है कि, हर बार जब आप किसी विधि को कॉल करते हैं तो एक ही काम करने के बजाय, आप वापसी मूल्य को एक चर में सहेजते हैं और इसके बजाय इसका उपयोग करते हैं।

यहाँ यह स्यूडोकोड में कैसा दिखता है:

def my_method
  @memo = <work> if @memo is undefined
  return @memo
end

और यहां आप इसे रूबी में कैसे करते हैं। यह सबसे मजबूत दृष्टिकोण है, लेकिन यह काफी क्रियात्मक है। अन्य, अधिक संक्षिप्त दृष्टिकोण हैं जिन पर हम बाद में चर्चा करेंगे।

class MyClass
  def my_method
    unless defined?(@my_method)
      @my_method = begin 
         # Do your calculation, database query
         # or other long-running thing here. 
      end
    end
    @my_method
  end
end

ऊपर दिया गया कोड तीन काम करता है:

  1. यह देखने के लिए जांचता है कि क्या @my_method . नामक एक आवृत्ति चर है .
  2. यदि है, तो यह कुछ काम करता है और परिणाम @my_method में सहेजता है ।
  3. यह @my_method लौटाता है

इस तथ्य से भ्रमित न हों कि हमारे पास my_method नामक एक विधि और एक आवृत्ति चर दोनों हैं . मैं अपने वेरिएबल को कुछ भी नाम दे सकता था, लेकिन इसे याद रखने की विधि के बाद इसे नाम देना परंपरा है।

एक शॉर्टहैंड संस्करण

उपरोक्त कोड के साथ एक समस्या यह है कि यह थोड़ा बोझिल है। इस वजह से, आपको एक शॉर्टहैंड संस्करण देखने की अधिक संभावना है जो लगभग एक ही काम करता है:

class MyClass
  def my_method1
    @my_method1 ||= some_long_calculation
  end

  def my_method2
    @my_method2 ||= begin
      # The begin-end block lets you easily 
      # use multiple lines of code here. 
    end
  end
end

ये दोनों रूबी के a ||= b . का उपयोग करते हैं ऑपरेटर, जो a || (a = b) , जो स्वयं के लिए कमोबेश आशुलिपि है:

# You wouldn't use return like this in real life. 
# I'm just using it to express to beginners the idea
# that the conditional evaluates to whatever winds up in `a`.
if a
  return a
else
  a = b
  return a
end

बग का स्रोत

यदि आप बहुत करीब से ध्यान दे रहे हैं तो आपने देखा होगा कि शॉर्टहैंड संस्करण मेमो वेरिएबल के अस्तित्व की जांच करने के बजाय "सत्यता" का मूल्यांकन करते हैं। यह शॉर्टहैंड संस्करण की प्रमुख सीमाओं में से एक का स्रोत है:यह कभी भी nil को याद नहीं करता है या false .

ऐसे बहुत से उपयोग के मामले हैं जहां यह महत्वपूर्ण नहीं है। लेकिन यह उन कष्टप्रद तथ्यों में से एक है जिसे आपको याद करते समय अपने दिमाग में रखना होगा।

तर्कों के साथ याद रखने के तरीके

अब तक हमने केवल एकल मूल्यों को याद रखने के बारे में बात की है। लेकिन कई फ़ंक्शन हर समय एक ही परिणाम नहीं देते हैं। आइए तकनीकी साक्षात्कारों के पुराने पसंदीदा पर एक नज़र डालें:फाइबोनैचि अनुक्रम।

आप रूबी में फिबोनाची अनुक्रम की पुनरावर्ती रूप से गणना कर सकते हैं जैसे:

class Fibonacci
  def self.calculate(n)
    return n if n == 0 || n == 1
    calculate(n - 1) + calculate(n - 2)
  end
end

Fibonacci.calculate(10) # => 55

इस कार्यान्वयन के साथ समस्या यह है कि यह अक्षम है। इसे साबित करने के लिए, आइए एक printजोड़ें n . का मान देखने के लिए कथन ।

class Fibonacci
  def self.calculate(n)
    print "#{ n } "
    return n if n == 0 || n == 1
    calculate(n - 1) + calculate(n - 2)
  end
end

Fibonacci.calculate(4)

# Outputs: 4 3 2 1 0 1 2 1 0

जैसा कि आप देख सकते हैं, calculate n . के कई समान मानों के साथ बार-बार कॉल किया जा रहा है . वास्तव में calculate करने के लिए कॉल की संख्या n . के साथ तेजी से बढ़ने वाला है .

इसका एक तरीका calculate . के परिणामों को याद रखना है . ऐसा करना हमारे द्वारा कवर किए गए अन्य संस्मरण उदाहरणों से बहुत अलग नहीं है।

class Fibonacci
  def self.calculate(n)
    @calculate ||= {}
    @calculate[n] ||= begin
      print "#{ n } "
      if n == 0 || n == 1
        n
      else
        calculate(n - 1) + calculate(n - 2)
      end
    end
  end
end

Fibonacci.calculate(4)

# Outputs: 4 3 2 1 0

अब जबकि हमने calculate याद कर लिया है , कॉल की संख्या अब n . के साथ तेजी से नहीं बढ़ती है ।

Fibonacci.calculate(20)

# Outputs: 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

अमान्यता

संस्मरण कैशिंग की तरह है, सिवाय इसके कि याद किए गए परिणाम स्वचालित रूप से समाप्त नहीं होते हैं, और आमतौर पर एक बार सेट होने पर उन्हें साफ़ करने का कोई आसान तरीका नहीं होता है।

फाइबोनैचि अनुक्रम जनरेटर जैसे उपयोग के मामलों के लिए यह शायद ही मायने रखता है। Fibonacci.calculate(10) हमेशा एक ही परिणाम लौटाएगा। लेकिन अन्य उपयोग के मामलों में यह मायने रखता है।

उदाहरण के लिए, आपको इस तरह का कोड दिखाई दे सकता है:

# Not the best idea
class User
  def full_name
    @full_name ||= [first_name, last_name].join(" ")
  end
end

व्यक्तिगत रूप से, मैं यहां संस्मरण का उपयोग नहीं करूंगा क्योंकि यदि पहला या अंतिम नाम बदल दिया जाता है, तो पूरा नाम अपडेट नहीं किया जा सकता है।

एक जगह जहां आप थोड़ा और ढीला हो सकते हैं वह रेल नियंत्रकों के अंदर है। इस तरह का कोड देखना बहुत आम है:

class ApplicationController
  def current_user
    @current_user ||= User.find(...)
  end
end

यह ठीक है, क्योंकि प्रत्येक वेब अनुरोध के बाद नियंत्रक उदाहरण नष्ट हो जाता है। यह संभावना नहीं है कि वर्तमान में लॉग-इन उपयोगकर्ता किसी सामान्य अनुरोध के दौरान बदल जाएगा।

एक्शनकेबल जैसे स्ट्रीमिंग कनेक्शन के साथ काम करते समय आपको अधिक सावधान रहने की आवश्यकता हो सकती है। मुझें नहीं पता। मैंने कभी इसका इस्तेमाल नहीं किया।

अति प्रयोग

अंत में मुझे ऐसा लगता है कि मुझे यह बताना चाहिए कि किसी भी चीज़ की तरह, संस्मरण को बहुत दूर ले जाना संभव है। यह एक ऐसी तकनीक है जिसे वास्तव में केवल महंगे संचालन पर लागू किया जाना चाहिए जो मेमो चर के पूरे जीवनकाल में कभी नहीं बदलेगा।


  1. रूबीस्ट्स गाइड टू एनवायरनमेंट वेरिएबल्स

    यदि आप विकास और उत्पादन में वेब ऐप्स को प्रभावी ढंग से प्रबंधित करने में सक्षम होना चाहते हैं, तो आपको पर्यावरण चर को समझना होगा। यह हमेशा मामला नहीं था। कुछ साल पहले, शायद ही कोई अपने रेल ऐप्स को पर्यावरण चर के साथ कॉन्फ़िगर कर रहा था। लेकिन फिर हेरोकू हुआ। हरोकू ने डेवलपर्स को 12-कारक ऐप दृष्टिक

  1. रूबी में इनपुट और आउटपुट (आईओ):निश्चित गाइड

    I/O का मतलब इनपुट/आउटपुट है। इनपुट से हमारा मतलब उन सभी डेटा और सूचनाओं से है जो किसी चीज़ में आती हैं (कंप्यूटर, रूबी विधि, आपका दिमाग)। इनपुट के उदाहरण : कीबोर्ड पर आपके प्रेस की कुंजी माउस क्लिक आपके द्वारा पढ़ी जाने वाली पुस्तकें आउटपुट से हमारा मतलब वह सब कुछ है जो इनपुट के परिणामस्वरूप नि

  1. Mac Security:The Essential Guide

    क्या Mac को एंटीवायरस की आवश्यकता है? मैक के पास दशकों से असाधारण सुरक्षा रिकॉर्ड रहे हैं, मुख्यतः दो कारणों से। एक यह है कि मैक मजबूत सुरक्षात्मक सुविधाओं के साथ बनाए गए हैं और बहुत कम शोषक कमजोरियां . दूसरी बात यह है कि अधिकांश दुनिया के पास पीसी हैं, इसलिए साइबर अपराधियों ने अपने अधिकांश प्रयासो