2011-11-23 8 views
12

मैं मौजूदा जावा सॉफ़्टवेयर का स्मृति विश्लेषण कर रहा हूं। क्या समान वर्गों के साथ ऑब्जेक्ट्स की गिनती देखने के लिए ओकएल में बराबर एक वर्ग 'समूह' है लेकिन अलग-अलग उदाहरण हैं। s.toString द्वारा java.lang.String रों समूह सेओक के साथ जावा ढेर विश्लेषण: अद्वितीय तारों की गणना करें

चयन गिनती (*) ()

मैं डुप्लिकेट की संख्या के साथ डुप्लिकेट स्ट्रिंग की एक सूची प्राप्त करने के लिए करना चाहते हैं। इसका उद्देश्य बड़ी संख्या में मामलों को देखना है ताकि उन्हें String.intern() का उपयोग करके अनुकूलित किया जा सके।

उदाहरण:

"foo" 100 
"bar" 99 
"lazy fox" 50 

आदि ...

उत्तर

19

निम्नलिखित पीटर Dolberg द्वारा जवाब पर आधारित है और VisualVM OQL कंसोल में इस्तेमाल किया जा सकता:

var counts={}; 
var alreadyReturned={}; 

filter(
    sort(
    map(heap.objects("java.lang.String"), 
    function(heapString){ 
     if(! counts[heapString.toString()]){ 
     counts[heapString.toString()] = 1; 
     } else { 
     counts[heapString.toString()] = counts[heapString.toString()] + 1; 
     } 
     return { string:heapString.toString(), count:counts[heapString.toString()]}; 
    }), 
    'lhs.count < rhs.count'), 
    function(countObject) { 
    if(! alreadyReturned[countObject.string]){ 
     alreadyReturned[countObject.string] = true; 
     return true; 
    } else { 
     return false; 
    } 
    } 
); 

यह बना कर या किसी को अद्यतन करने के सभी स्ट्रिंग उदाहरणों पर और प्रत्येक स्ट्रिंग के लिए एक map() कॉल का उपयोग करके शुरू होता है counts सरणी में ऑब्जेक्ट। प्रत्येक ऑब्जेक्ट में string और count फ़ील्ड है।

परिणामी सरणी में प्रत्येक स्ट्रिंग आवृत्ति के लिए एक प्रविष्टि होगी, प्रत्येक में count एक ही स्ट्रिंग के लिए पिछली प्रविष्टि की तुलना में एक बड़ा मान होगा। परिणाम तो count मैदान पर क्रमबद्ध किया जाता है और परिणाम कुछ इस तरह दिखता है:

{ 
count = 1028.0, 
string = *null* 
} 

{ 
count = 1027.0, 
string = *null* 
} 

{ 
count = 1026.0, 
string = *null* 
} 

... 

(अपने परीक्षण में स्ट्रिंग "*null*" सबसे आम था)।

अंतिम चरण यह एक फ़ंक्शन का उपयोग करके फ़िल्टर करना है जो प्रत्येक स्ट्रिंग की पहली घटना के लिए सत्य लौटाता है। यह ट्रैक रखने के लिए alreadyReturned सरणी का उपयोग करता है कि कौन से स्ट्रिंग्स को पहले से ही शामिल किया जा चुका है।

+1

धन्यवाद जो अच्छी तरह से समस्या हल करता है। ओक्यूएल किसी भी तरह का उपयोग करने के लिए अजीब है। यह सब एक समारोह में होना है ... – paweloque

+0

वाह, यह नहीं पता था कि jvisualvm वह शक्तिशाली है। मुझे कुछ स्ट्रिंग्स के लिए उच्च गिनती मान मिलते हैं - क्या आपका कोड कचरा छोड़ देता है (संदर्भित स्ट्रिंग्स नहीं)? – Jan

+1

यह सभी java.lang.String वस्तुओं को ढेर पर खोजने के लिए "heap.objects" का उपयोग करता है। गैर-संदर्भित स्ट्रिंग को बाहर करने के लिए कोई फ़िल्टरिंग नहीं है। लेकिन हेप डंप कैसे उत्पन्न हुआ था, इस पर निर्भर करता है कि जेवीएम ने पहले एक पूर्ण जीसी किया होगा, इस मामले में किसी भी गैर-संदर्भित स्ट्रिंग को पहले ही हटा दिया जाना चाहिए और ढेर डंप में शामिल नहीं होना चाहिए। –

2

दुख की बात है, वहाँ एक बराबर करने के लिए "समूह द्वारा" OQL में नहीं है। मुझे लगता है कि आप ओक्यूएल के बारे में बात कर रहे हैं जिसका उपयोग जाट और विजुअलVM में किया जाता है।

हालांकि, एक विकल्प है। यदि आप "एक्स से एक्स एक्स" सिंटैक्स के बजाय शुद्ध जावास्क्रिप्ट सिंटैक्स का उपयोग करते हैं तो आपके पास काम करने के लिए जावास्क्रिप्ट की पूरी शक्ति है।

फिर भी, जो जानकारी आप खोज रहे हैं उसे पाने का वैकल्पिक तरीका सरल नहीं है। एक नियमित रूप से जावास्क्रिप्ट वस्तु की नकल करता है एक सेट (कोई डुप्लिकेट के साथ संग्रह) इस उदाहरण में

var set={}; 
sum(map(heap.objects("java.lang.String"),function(heapString){ 
    if(set[heapString.toString()]){ 
    return 0; 
    } 
    else{ 
    set[heapString.toString()]=true; 
    return 1; 
    } 
})); 

: उदाहरण के लिए, यहाँ एक OQL "क्वेरी" आपकी क्वेरी के रूप में ही कार्य करेगा। चूंकि नक्शा फ़ंक्शन प्रत्येक स्ट्रिंग के माध्यम से जाता है, सेट का उपयोग यह निर्धारित करने के लिए किया जाता है कि स्ट्रिंग पहले ही देखी जा चुकी है या नहीं। डुप्लिकेट कुल (वापसी 0) की ओर गिनती नहीं करते हैं लेकिन नए तार करते हैं (वापसी 1)।

+0

हाय पीटर, आपकी क्वेरी के लिए धन्यवाद, यह मेरे दिशा में लाता है, लेकिन मैं अभी तक वहाँ नहीं कर रहा हूँ :) इस क्वेरी मैं डुप्लिकेट की कुल संख्या देखने के साथ तार। मैं जो देखना चाहता हूं वह स्ट्रिंग और दोहराना-संख्या है: 'foo' 10 बार, 'बार' 100 बार, आदि .. यह देखने के लिए कि मैंने सेट की सामग्री को आउटपुट करने का प्रयास किया है, लेकिन मुझे केवल अजीब जेस्क्रिप्ट अपवाद मिलते हैं .. क्या आपको पता है कि मैं क्या देखना चाहता हूं? – paweloque

7

मैं इसके बजाय Eclipse Memory Analyzer का उपयोग करूंगा।

+2

मुझे वास्तव में आपका प्रस्ताव पसंद है क्योंकि यह समस्या को बहुत अच्छी तरह से हल करता है। हालांकि, मुझे उम्मीद है कि आप समझेंगे कि ओक्ल लिखने के लिए जोहान काविंग जाता है। मुझे लगता है कि ऐसी स्थितियां हो सकती हैं जहां ओकएल को समझना उपयोगी हो। लेकिन हालांकि धन्यवाद! – paweloque

+0

ऐसा करने के लिए ओपन क्वेरी ब्राउज़र -> जावा मूल बातें -> समूह द्वारा मूल्य का उपयोग करें। ऑब्जेक्ट्स के लिए 'java.lang.String' चुनें और फ़ील्ड के लिए' value' चुनें। – kichik

0

अन्य संदर्भों के लिए समान समस्या करते समय बस अपना समाधान और अनुभव पोस्ट करें।

var counts = {}; 
var alreadyReturned = {}; 
top(
filter(
    sort(
     map(heap.objects("java.lang.ref.Finalizer"), 
      function (fobject) { 
       var className = classof(fobject.referent) 
       if (!counts[className]) { 
        counts[className] = 1; 
       } else { 
        counts[className] = counts[className] + 1; 
       } 
       return {string: className, count: counts[className]}; 
      }), 
     'rhs.count-lhs.count'), 
    function (countObject) { 
     if (!alreadyReturned[countObject.string]) { 
      alreadyReturned[countObject.string] = true; 
      return true; 
     } else { 
      return false; 
     } 
    }), 
    "rhs.count > lhs.count", 10); 

पिछले कोड इच्छा उत्पादन शीर्ष 10 java.lang.ref.Finalizer द्वारा इस्तेमाल किया कक्षाओं।
युक्तियाँ:
1. फ़ंक्शन XXX का उपयोग करके सॉर्ट फ़ंक्शन मेरे मैक ओएस पर काम नहीं कर रहा है।
2. क्लासफ फ़ंक्शन रेफरेंस की कक्षा को वापस कर सकता है। (मैंने fobject.referent.toString() -> का उपयोग करने की कोशिश की -> यह बहुत से org.netbeans.lib.profiler.heap.InstanceDump लौटा। यह भी मेरा बहुत समय बर्बाद कर दिया)।

1

एक कहीं अधिक कुशल क्वेरी:

var countByValue = {}; 

// Scroll the strings 
heap.forEachObject(
    function(strObject) { 
    var key = strObject.toString(); 
    var count = countByValue[key]; 
    countByValue[key] = count ? count + 1 : 1; 
    }, 
    "java.lang.String", 
    false 
); 

// Transform the map into array 
var mapEntries = []; 
for (var i = 0, keys = Object.keys(countByValue), total = keys.length; i < total; i++) { 
    mapEntries.push({ 
    count : countByValue[keys[i]], 
    string : keys[i] 
    }); 
} 

// Sort the counts 
sort(mapEntries, 'rhs.count - lhs.count'); 
संबंधित मुद्दे