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

रूबी इंटर्नल्स:रूबी ऑब्जेक्ट्स के मेमोरी लेआउट को एक्सप्लोर करना

क्या आप रूबी इंटर्नल का एक त्वरित दौरा चाहेंगे?

फिर आप एक दावत के लिए तैयार हैं।

क्योंकि

हम एक साथ यह पता लगाने जा रहे हैं कि रूबी ऑब्जेक्ट को मेमोरी में कैसे रखा जाता है और आप कुछ अच्छी चीजें करने के लिए आंतरिक डेटा संरचनाओं में कैसे हेरफेर कर सकते हैं।

अपनी सीट बेल्ट बांधें और रूबी दुभाषिया की गहराई में यात्रा के लिए तैयार हो जाएं!

सरणी का मेमोरी लेआउट

जब आप एक ऐरे बनाते हैं, तो रूबी को कुछ सिस्टम मेमोरी और थोड़े से मेटाडेटा के साथ उसका बैकअप लेना पड़ता है।

मेटाडेटा में शामिल हैं :

  • सरणी आकार (आइटम गणना)
  • सरणी क्षमता
  • कक्षा
  • वस्तु स्थिति (जमे हुए या नहीं)
  • यह इंगित करता है कि डेटा मेमोरी में कहाँ संग्रहीत है

चूंकि मुख्य रूबी दुभाषिया (एमआरआई) सी में लिखा गया है, इसलिए कोई वस्तु नहीं है।

लेकिन कुछ और है:structs

C में एक स्ट्रक्चर आपको संबंधित डेटा को एक साथ स्टोर करने में मदद करता है, और इसका उपयोग MRI के सोर्स कोड में Array जैसी चीजों को दर्शाने के लिए किया जाता है। , String और अन्य प्रकार की वस्तुएं।

इनमें से किसी एक स्ट्रक्चर को देखकर हम किसी ऑब्जेक्ट के मेमोरी लेआउट का अनुमान लगा सकते हैं।

तो आइए Array . के लिए स्ट्रक्चर देखें , जिसे RArray . कहा जाता है :

struct RArray {
  struct RBasic basic;

  union {
    struct {
      long len;

      union {
        long capa;
        VALUE shared;
      } aux;

      const VALUE *ptr;
    } heap;

    const VALUE ary[RARRAY_EMBED_LEN_MAX];
  } as;
};

मुझे पता है कि अगर आप सी से परिचित नहीं हैं तो यह थोड़ा डरावना लग सकता है, लेकिन चिंता न करें! मैं इसे आसानी से पचने वाले बिट्स में तोड़ने में आपकी मदद करूंगा 🙂

हमारे पास सबसे पहली चीज यह है RBasic चीज़, जो एक संरचना भी है:

struct RBasic {
  VALUE flags;
  VALUE klass;
}

यह कुछ ऐसा है जो अधिकांश रूबी वस्तुओं में होता है और इसमें कुछ चीजें होती हैं जैसे इस वस्तु के लिए वर्ग और कुछ बाइनरी झंडे जो कहते हैं कि यह वस्तु जमी हुई है या नहीं (और अन्य चीजें जैसे 'दागी' विशेषता)।

दूसरे शब्दों में :

RBasic ऑब्जेक्ट के लिए सामान्य मेटाडेटा शामिल है।

उसके बाद हमारे पास एक और स्ट्रक्चर होता है, जिसमें ऐरे की लंबाई होती है (len )।

संघ अभिव्यक्ति कह रही है कि aux या तो capa . हो सकता है (क्षमता के लिए) या shared . यह ज्यादातर एक अनुकूलन चीज है, जिसे पैट शौघनेस द्वारा इस उत्कृष्ट पोस्ट में अधिक विस्तार से समझाया गया है। स्मृति आवंटन के संदर्भ में, संकलक संघ के अंदर सबसे बड़े प्रकार का उपयोग करेगा।

फिर हमारे पास ptr . है , जिसमें स्मृति पता होता है जहां वास्तविक Array डेटा संग्रहीत किया जाता है।

यह कैसा दिखता है इसकी एक तस्वीर यहां दी गई है (प्रत्येक सफेद/ग्रे बॉक्स 32-बिट सिस्टम में 4 बाइट्स है ):

रूबी इंटर्नल्स:रूबी ऑब्जेक्ट्स के मेमोरी लेआउट को एक्सप्लोर करना

आप ऑब्जेक्टस्पेस मॉड्यूल का उपयोग करके किसी ऑब्जेक्ट का मेमोरी आकार देख सकते हैं:

require 'objspace'

ObjectSpace.memsize_of([])
# 20

अब हम कुछ मज़ा लेने के लिए तैयार हैं!

बेला:एक मजेदार प्रयोग

आरबीसिक 32-बिट सिस्टम में बिल्कुल 8 बाइट्स और 64-बिट सिस्टम में 16 बाइट्स है। यह जानने के बाद हम किसी ऑब्जेक्ट के लिए कच्ची मेमोरी बाइट्स तक पहुंचने के लिए फिडल मॉड्यूल का उपयोग कर सकते हैं और कुछ मजेदार प्रयोगों के लिए उन्हें बदल सकते हैं।

उदाहरण के लिए :

हम एक बिट को टॉगल करके फ़्रीज़ की गई स्थिति को बदल सकते हैं।

यह संक्षेप में है कि फ़्रीज़ विधि क्या करती है, लेकिन ध्यान दें कि कैसे कोई अनफ़्रीज़ विधि नहीं है।

आइए इसे केवल मनोरंजन के लिए लागू करें!

सबसे पहले, आवश्यकता है Fiddle मॉड्यूल (रूबी स्टैंडर्ड लाइब्रेरी का हिस्सा) और एक फ्रोजन स्ट्रिंग बनाएं।

require 'fiddle'

str = 'water'.freeze
str.frozen?
# true

अगला:

हमें अपने स्ट्रिंग के लिए मेमोरी एड्रेस चाहिए, जिसे इस तरह प्राप्त किया जा सकता है।

memory_address = str.object_id * 2

अंत में:

हम ठीक उसी बिट को फ्लिप करते हैं जिसे रूबी यह देखने के लिए जांचती है कि कोई वस्तु जमी हुई है या नहीं। हम यह देखने के लिए भी जांचते हैं कि क्या यह frozen? . को कॉल करके काम करता है विधि।

Fiddle::Pointer.new(memory_address)[1] ^= 8

str.frozen?
# false

ध्यान दें कि सूचकांक [1] झंडे . के दूसरे बाइट को संदर्भित करता है मान (जो कुल 4 बाइट्स से बना है)।

फिर हम ^= . का उपयोग करते हैं जो उस बिट को फ्लिप करने के लिए "XOR" (Exclusive OR) ऑपरेटर है।

हम ऐसा इसलिए करते हैं क्योंकि झंडे . के अंदर अलग-अलग बिट अलग-अलग अर्थ हैं और हम कुछ असंबंधित बदलना नहीं चाहते हैं।

अगर आपने मेरी रूबी ट्रिक्स पोस्ट पढ़ी है तो आपने इसे पहले देखा होगा, लेकिन अब आप जानते हैं कि यह कैसे काम करता है 🙂

एक और चीज जिसे आप आजमा सकते हैं वह है सरणी की लंबाई बदलना और सरणी को प्रिंट करना।

आप देखेंगे कि सरणी कैसे छोटी हो जाती है!

आप Array . बनाने के लिए कक्षा को बदल भी सकते हैं लगता है कि यह एक String है …

निष्कर्ष

आपने कुछ सीखा है कि रूबी हुड के नीचे कैसे काम करती है। रूबी ऑब्जेक्ट्स के लिए मेमोरी कैसे निर्धारित की जाती है और आप Fiddle . का उपयोग कैसे कर सकते हैं इसके साथ खेलने के लिए मॉड्यूल।

आपको शायद Fiddle . का उपयोग नहीं करना चाहिए इसे वास्तविक ऐप में पसंद करें, लेकिन इसके साथ प्रयोग करना मज़ेदार है।

इस पोस्ट को शेयर करना न भूलें ताकि और लोग इसे देख सकें 🙂


  1. रूबी में एक प्रोग्रामिंग भाषा का निर्माण:पार्सर

    Github पर पूर्ण स्रोत स्टॉफ़ल प्रोग्रामिंग भाषा का पूर्ण कार्यान्वयन GitHub पर उपलब्ध है। कोड को पढ़ने को आसान बनाने में मदद करने के लिए इस संदर्भ कार्यान्वयन में बहुत सारी टिप्पणियाँ हैं। अगर आपको बग मिलते हैं या आपके कोई प्रश्न हैं, तो बेझिझक कोई समस्या खोलें। इस ब्लॉग पोस्ट में, हम स्टॉफ़ल के

  1. रूबी में डेकोरेटर डिजाइन पैटर्न

    डेकोरेटर डिजाइन पैटर्न क्या है? और आप अपने रूबी प्रोजेक्ट्स में इस पैटर्न का उपयोग कैसे कर सकते हैं? डेकोरेटर डिज़ाइन पैटर्न नई क्षमताओं . जोड़कर किसी ऑब्जेक्ट को बेहतर बनाने में आपकी सहायता करता है इसमें बिना कक्षा बदले। आइए एक उदाहरण देखें! लॉगिंग और प्रदर्शन इस उदाहरण में हम रेस्ट-क्लाइंट जैस

  1. टीसीमॉलोक के साथ रूबी की मेमोरी आवंटन की रूपरेखा

    रूबी में मेमोरी आवंटन कैसे काम करता है? रूबी को मेमोरी टुकड़ों में मिलती है, जिन्हें पेज कहा जाता है, यहां नई वस्तुएं सहेजी जाती हैं। फिर… जब ये पृष्ठ भर जाते हैं, तो अधिक स्मृति की आवश्यकता होती है। रूबी ऑपरेटिंग सिस्टम से malloc . के साथ अधिक मेमोरी का अनुरोध करती है समारोह। यह malloc फ़ंक्श