क्या आप रूबी इंटर्नल का एक त्वरित दौरा चाहेंगे?
फिर आप एक दावत के लिए तैयार हैं।
क्योंकि …
हम एक साथ यह पता लगाने जा रहे हैं कि रूबी ऑब्जेक्ट को मेमोरी में कैसे रखा जाता है और आप कुछ अच्छी चीजें करने के लिए आंतरिक डेटा संरचनाओं में कैसे हेरफेर कर सकते हैं।
अपनी सीट बेल्ट बांधें और रूबी दुभाषिया की गहराई में यात्रा के लिए तैयार हो जाएं!
सरणी का मेमोरी लेआउट
जब आप एक ऐरे बनाते हैं, तो रूबी को कुछ सिस्टम मेमोरी और थोड़े से मेटाडेटा के साथ उसका बैकअप लेना पड़ता है।
मेटाडेटा में शामिल हैं :
- सरणी आकार (आइटम गणना)
- सरणी क्षमता
- कक्षा
- वस्तु स्थिति (जमे हुए या नहीं)
- यह इंगित करता है कि डेटा मेमोरी में कहाँ संग्रहीत है
चूंकि मुख्य रूबी दुभाषिया (एमआरआई) सी में लिखा गया है, इसलिए कोई वस्तु नहीं है।
लेकिन कुछ और है: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
. का उपयोग नहीं करना चाहिए इसे वास्तविक ऐप में पसंद करें, लेकिन इसके साथ प्रयोग करना मज़ेदार है।
इस पोस्ट को शेयर करना न भूलें ताकि और लोग इसे देख सकें 🙂