2015-10-03 8 views
20

मैं समझने की कोशिश कर रहा हूं कि रूबी ढेर से आवंटित स्मृति ऑपरेटिंग सिस्टम में वापस आती है। मैं समझता हूं कि रुबी कभी भी ढेर में आवंटित स्मृति वापस नहीं लौटाती है, लेकिन मुझे अभी भी ढेर स्मृति के व्यवहार के बारे में निश्चित नहीं है। यानी वे ऑब्जेक्ट्स जो 40 बाइट आरवीALUE में फिट नहीं होते हैं।यह रूबी प्रोग्राम ऑपरेटिंग सिस्टम में ढेर मेमोरी क्यों नहीं लौटाता है?

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

require 'objspace' 

STRING_SIZE = 250 

def print_stats(msg) 
    puts '-------------------' 
    puts msg 
    puts '-------------------' 
    puts "RSS: #{`ps -eo rss,pid | grep #{Process.pid} | grep -v grep | awk '{ print $1,"KB";}'`}" 
    puts "HEAP SIZE: #{(GC.stat[:heap_sorted_length] * 408 * 40)/1024} KB" 
    puts "SIZE OF ALL OBJECTS: #{ObjectSpace.memsize_of_all/1024} KB" 
end 

def run 
    print_stats('START WORK') 
    @data=[] 
    600_000.times do 
    @data << " " * STRING_SIZE 
    end 
    print_stats('END WORK') 
    @data=nil 
end 

run 
GC.start 
print_stats('AFTER FORCED MAJOR GC') 

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

------------------- 
START WORK 
------------------- 
RSS: 7036 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 3172 KB 
------------------- 
END WORK 
------------------- 
RSS: 205660 KB 
HEAP SIZE: 35046 KB 
SIZE OF ALL OBJECTS: 178423 KB 
------------------- 
AFTER FORCED MAJOR GC 
------------------- 
RSS: 164492 KB 
HEAP SIZE: 35046 KB 
SIZE OF ALL OBJECTS: 2484 KB 

इन परिणामों की तुलना निम्न परिणामों पर करें जब हम कई छोटी वस्तुओं के बजाय एक बड़ी वस्तु आवंटित करते हैं।

def run 
    print_stats('START WORK') 
    @data = " " * STRING_SIZE * 600_000 
    print_stats('END WORK') 
    @data=nil 
end 

------------------- 
START WORK 
------------------- 
RSS: 7072 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 3170 KB 
------------------- 
END WORK 
------------------- 
RSS: 153584 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 149064 KB 
------------------- 
AFTER FORCED MAJOR GC 
------------------- 
RSS: 7096 KB 
HEAP SIZE: 1195 KB 
SIZE OF ALL OBJECTS: 2483 KB 

अंतिम आरएसएस मूल्य नोट करें। ऐसा लगता है कि हमने बड़ी स्ट्रिंग के लिए आवंटित सभी मेमोरी को मुक्त कर दिया है।

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

कर्नेल को वापस स्मृति को रिहा करने के लिए भी लागत है। उपयोगकर्ता स्पेस मेमोरी आवंटक उम्मीद में उस स्मृति (निजी रूप से) पर हो सकते हैं, यह एक ही प्रक्रिया में पुन: उपयोग किया जा सकता है और अन्य प्रक्रियाओं में उपयोग के लिए कर्नेल को वापस नहीं दे सकता है।

+1

इस सूत्र को सब्सक्राइब करना। मैं भी इसमें बहुत दिलचस्पी रखता हूं। – dimitarvp

+1

मौलिक अंतर 1 उदाहरण में है, जहां 600k * नई * वस्तुओं को केवल दूसरे में बनाया गया है। यद्यपि * संदर्भित * डेटा का कुल आकार समान है, लेकिन पहले उदाहरण के लिए ऑब्जेक्ट्स संदर्भित करने के लिए 600 हजार गुना अधिक स्लॉट की आवश्यकता होती है (जो संभवतः कभी भी ओएस पर पुनः दावा नहीं किया जाता है)। – joanbm

+2

मैं निम्नलिखित [आलेख] (http://www.sitepoint.com/ruby-uses-memory/) सुझाता हूं और लिंक [स्पष्टीकरण] (http://rocket-science.ru/hacking/2013/12/17/रूबी-मेमोरी-pitfalls /) 'RVALUE की। मुझे यकीन नहीं है कि वे काफी सही हैं, केवल कोइची उर्फ ​​को 1 खुद ही जान सकते हैं। या कुछ दृढ़ता से दृढ़ उत्साही, रूबी स्रोतों का विश्लेषण। – joanbm

उत्तर

1

@joanbm का यहां एक बहुत अच्छा बिंदु है। उनके संदर्भित article explains this pretty well:

रुबी का जीसी धीरे-धीरे स्मृति जारी करता है, इसलिए जब आप 1 संदर्भ द्वारा इंगित स्मृति के 1 बड़े हिस्से पर जीसी करते हैं तो यह सब रिलीज़ करता है, लेकिन जब बहुत सारे संदर्भ होते हैं, तो जीसी छोटी स्मृति में रिलीज करेगा chuncks।

GC.start पर कई कॉल 1 उदाहरण में अधिक से अधिक स्मृति जारी करेंगे।


यहाँ बेहतर जानकारी के लिए 2 orther लेख हैं:

संबंधित मुद्दे