2012-05-05 9 views
8

जब मैं इसे चलाता हूं और फिर ओएसएक्स गतिविधि मॉनिटर में मेरी रूबी प्रक्रिया की स्मृति खपत देखता हूं, तो स्मृति लगभग 3 एमबी/एस में बढ़ जाती है।कई नई ऑब्जेक्ट्स बनाते समय मेमोरी ब्लोट

यदि मैं लेनदेन को हटा देता हूं तो यह स्मृति की खपत को कम करता है लेकिन फिर भी, स्मृति पदचिह्न जारी रहता है। मुझे अपने उत्पादन ऐप पर कोई समस्या है जहां हरोकू अपनी स्मृति खपत के कारण प्रक्रिया को मारता है।

क्या नीचे ऐसा करने का कोई तरीका है, इस तरह से स्मृति में वृद्धि नहीं होगी? अगर मैं .save लाइन पर टिप्पणी करता हूं तो यह ठीक है लेकिन निश्चित रूप से यह कोई समाधान नहीं है।

ActiveRecord::Base.transaction do 
    10000000.times do |time| 
    puts "---- #{time} ----" 
    a = Activity.new(:name => "#{time} Activity") 
    a.save!(:validate => false) 
    a = nil 
    end 
end 

मैं इसे delayed_job का उपयोग कर चला रहा हूं।

+0

अपने कचरा कलेक्टर Finetune लेकिन यह एक मुश्किल काम है ... – apneadiving

+1

@Morgz आप रूबी और रेल के किस संस्करण का उपयोग कर रहे हैं? – Matty

+0

@ मैटी रेल 3.1.0 – Morgz

उत्तर

4

a = nil लाइन अनावश्यक है और आप इसे हटा सकते हैं।

हर बार जब आप लूप - दो स्ट्रिंग, दो हैंश और एक गतिविधि ऑब्जेक्ट करते हैं तो आप बहुत सारी ऑब्जेक्ट्स बना रहे हैं, इसलिए मुझे आश्चर्य नहीं है कि आप उच्च मेमोरी उपयोग का अनुभव कर रहे हैं, खासकर जब आप 10 मिलियन बार लूप कर रहे हैं ! इस कोड को लिखने के लिए एक और अधिक मेमोरी प्रभावी तरीका प्रतीत नहीं होता है।

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

GC is here के लिए प्रलेखन।

+0

मेरे ज्ञान के आधार पर, आप केवल जीसी चलाने के लिए रूबी को "सुझाव" दे सकते हैं। लेकिन यह अभी भी – K2xL

+0

@ K2xL काम कर सकता है मैं इसके बारे में इतना निश्चित नहीं हूं। आप 'जीसी.स्टार्ट' को कॉल करके जीसी को मजबूर कर सकते हैं। हालांकि मुझे अन्यथा दिखाया जाना पसंद है। दस्तावेज में कुछ भी नहीं है यह इंगित करने के लिए कि 'जीसी.स्टार्ट' कॉलिंग सलाहकार है। – Matty

+0

अरे मैट। दिलचस्प बात यह है कि लूप के भीतर जीसी.स्टार्ट को कॉल करना स्मृति से नियंत्रण से बाहर रहता है, लेकिन हाँ यह प्रदर्शन को बहुत प्रभावित करता है! तो मैंने सोचा कि मैं इसे हर 1000 बार आमंत्रित करने की कोशिश करता हूं। जीसी.स्टार्ट अगर समय% 1000 == 0 - यह काम नहीं करता है और मेमोरी सर्पिल ऊपर और नियंत्रण से बाहर है! तो फिलहाल केवल हर बार जीसी के लिए विकल्प है: -/ – Morgz

0

मैं जानता हूँ कि यह एक प्राचीन मुद्दा है, लेकिन मैं एक और कट्टरपंथी दृष्टिकोण का सुझाव है:

ActiveRecord::Base.transaction do 
    10000000.times do |time| 
    puts "---- #{time} ----" 
    sql = <<SQL 
INSERT INTO activities ("name") VALUES ("#{time}") 
SQL 
    Activity.connection.execute(sql) 
    end 
end 

बिंदु है यदि डालने कि आसान है, और आप पहले से ही किसी भी ActiveModel सत्यापन लंघन कर रहे हैं, यह है कि पहली जगह में Activerecord ऑब्जेक्ट को तुरंत चालू करने का कोई कारण नहीं है। आम तौर पर यह चोट नहीं पहुंचाएगा, लेकिन चूंकि यह आपको इस मामले में चोट पहुंचा रहा है, मुझे लगता है कि आप इस तरह से बहुत कम स्मृति का उपयोग करेंगे।

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