2013-04-09 9 views
5

मैंने एक साधारण B-Tree लागू किया है जो नक्शे को स्याही के लिए लंबे समय तक लागू करता है। अब मैं इसके बारे में स्मृति के उपयोग का अनुमान लगाने के लिए निम्न विधि का उपयोग करना चाहता था (JVM केवल 32bit पर लागू होता है):जावा में बी-ट्री के मेमोरी उपयोग की गणना

class BTreeEntry { 

    int entrySize; 
    long keys[]; 
    int values[]; 
    BTreeEntry children[]; 
    boolean isLeaf; 
    ... 
    /** @return used bytes */ 
    long capacity() { 
     long cap = keys.length * (8 + 4) + 3 * 12 + 4 + 1; 
     if (!isLeaf) { 
      cap += children.length * 4; 
      for (int i = 0; i < children.length; i++) { 
       if (children[i] != null) 
        cap += children[i].capacity(); 
      } 
     } 
     return cap; 
    } 
} 
/** @return memory usage in MB */ 
public int memoryUsage() { 
    return Math.round(rootEntry.capacity()/(1 << 20)); 
} 

लेकिन मैं इसे जैसे की कोशिश की 7mio प्रविष्टियों और मेमोरीयूज विधि के लिए -Xmx सेटिंग की तुलना में बहुत अधिक मूल्यों की रिपोर्ट करता है! जैसे यह 1040 (एमबी) और मैं सेट -Xmx300 सेट कहते हैं! क्या JVM मेमोरी लेआउट को अनुकूलित करने में सक्षम है, उदाहरण के लिए। खाली सरणी के लिए या मेरी गलती क्या हो सकती है?

अद्यतन 1: ठीक है, आईएसएलएफ़ बूलियन शुरू करने से स्मृति उपयोग बहुत कम हो जाता है, लेकिन फिर भी यह स्पष्ट नहीं है कि मैंने एक्सएमएक्स की तुलना में उच्च मूल्य क्यों देखा। (आप अभी भी सभी रचनाकारों के लिए isLeaf == झूठी का उपयोग करके इसे आजमा सकते हैं)

अद्यतन 2: हम्म, कुछ बहुत गलत है। प्रत्येक पत्ते में प्रविष्टियों को बढ़ाने पर, यह मान लेगा कि स्मृति उपयोग घटता है (दोनों के लिए कॉम्पैक्ट करते समय), क्योंकि संदर्भों के कम ओवरहेड बड़े सरणी के लिए शामिल होते हैं (और बीटी की छोटी ऊंचाई होती है)। लेकिन विधि मेमोरी यूजेज में बढ़ी हुई कीमत की रिपोर्ट है यदि मैं 500 प्रति लीटर प्रति 100 प्रविष्टियों का उपयोग करता हूं।

+0

लंबी क्षमता में 3 * 12 की उत्पत्ति क्या है? – Erik

+0

लंबी और int के स्मृति खपत मूल्यों के लिए आपका स्रोत क्या है। – PeterMmm

+0

@ एरिक 3 * 12 -> 3 सरणी के संदर्भ। – Karussell

उत्तर

0

ओह श ... थोड़ा ताजा हवा इस मुद्दे का समाधान किया;)

जब एक प्रवेश पूर्ण यह splitted हो जाएगा। अपने मूल विभाजन विधि checkSplitEntry में (जहाँ मैं स्मृति की बर्बादी से बचना चाहता था) मैं एक बड़ी स्मृति अपशिष्ट गलती की:

// left child: just copy pointer and decrease size to index 
BTreeEntry newLeftChild = this; 
newLeftChild.entrySize = splitIndex; 

समस्या है यहाँ, कि उम्र के बच्चों के संकेत अभी भी सुलभ हैं। और इसलिए, मेरी स्मृति में विधि विधि मैं कुछ बच्चों को दो बार गिन रहा हूं (विशेष रूप से जब मैंने कॉम्पैक्ट नहीं किया था!)। तो, इस चाल के बिना सभी ठीक होना चाहिए और मेरा बी-ट्री और भी मेमोरी कुशल होगा क्योंकि कचरा कलेक्टर अपना काम कर सकता है!

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