2011-12-05 13 views
5

शायद 5 या 6 SO पोस्ट हैं जो इस पर स्पर्श करते हैं, लेकिन कोई वास्तव में प्रश्न का उत्तर नहीं देता है।किसी ऑब्जेक्ट का मेमोरी उपयोग लॉगिंग

मेरे पास एक शब्दकोश वस्तु है जो मैं मूल्यों को स्टोर करने के लिए कैश के रूप में उपयोग करता हूं। समस्या यह है कि मुझे नहीं पता कि यह कितना बड़ा हो रहा है - समय के साथ यह बड़ा हो रहा है या नहीं, लेकिन मैं नहीं बता सकता और इसलिए मैं इसकी प्रभावशीलता को माप नहीं सकता, या इस बारे में निष्कर्ष निकाल सकता हूं कि उपयोगकर्ता सॉफ़्टवेयर का उपयोग कैसे कर रहा है । चूंकि यह एक ऐसा टुकड़ा है जो उत्पादन में जायेगा और बहुत लंबे समय तक कुछ की निगरानी करेगा, यह स्मृति प्रोफाइलर या इस तरह की कुछ भी डिबगगी को संलग्न करने का अर्थ नहीं है।

private void someTimer_Tick(object sender, EventArgs e) 
{ 
    ... 
    float mbMem = cacheMap.GetMemorySize(); 
    RecordInLog(DateTime.Now.ToString() + ": mbMem is using " + mbMem.ToString() + "MB of memory"); 
    ... 
} 

इस किया जा सकता है कुछ डिबग उपकरण संलग्न इतना है कि यह तैनात परिदृश्य इस्तेमाल किया जा सकता बिना:

आदर्श रूप में, मैं बस मेरी घड़ी में एक कॉल ऐसा ही कुछ करना होगा जगह होगा?

+2

शायद आप इसे पहले से ही देख चुके हैं, लेकिन बस मामले में - आप serrialization अनुमानित कर सकते हैं http://stackoverflow.com/questions/605621/how-to-get-object-size-in-memory – oleksii

+2

आवश्यक बाइट्स गिन रहा है ? बस कुंजी या अद्वितीय मानों की संख्या गिनती पर्याप्त हो सकती है? –

+0

@oleksii यह एकमात्र समाधान हो सकता है। मैं अभी भी चीजों को सीरियलाइज करते समय पर्याप्त प्रदर्शन हिट के आसपास एक रास्ता खोजने की कोशिश कर रहा हूं (यह एक बड़ी हिट है)। – kmarks2

उत्तर

1

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

आप अपने कैश की जरूरत है पूर्ण IDictionary कार्यक्षमता को बेनकाब करने के लिए, आप इंटरफ़ेस को लागू कर सकता है, "असली" शब्दकोश में नीचे सौंपने और Add और Remove आपरेशनों में संचयी आकार मूल्य को संशोधित। यदि आपको पूर्ण IDictionary कार्यक्षमता का पर्दाफाश करने के लिए अपने कैश की आवश्यकता नहीं है, तो बस एक स्ट्रिपेड डाउन इंटरफ़ेस (शायद Add, Contains, और Remove विधियों और CumulativeSize संपत्ति के साथ परिभाषित करें। या, आप इंटरफ़ेस के बिना कैशिंग ऑब्जेक्ट को कार्यान्वित करने का निर्णय ले सकते हैं । यदि यह मुझे थे, मैं IDictionary का प्रयोग करेंगे या तो या एक इंटरफेस को परिभाषित, ICache तरह

तो, अपने कैश इस (uncompiled और untested) की तरह कुछ दिख सकता है:।

public interface ICacheWithCumulativeSize 
{ 
    void Add(string key, string value); 
    bool Contains(string key); 
    void Remove(string key); 
    int CumulativeSize { get; } 
} 

public class MyCache : ICacheWithCumulativeSize 
{ 
    private IDictionary<string, string> dict = new Dictionary<string, string>(); 

    public void Add(string key, string value) 
    { 
    CumulativeSize += value.Length; 
    dict[key] = value; 
    } 

    public bool Contains(string key) 
    { 
    return dict.ContainsKey(key); 
    } 

    public void Remove(string key) 
    { 
    string toRemove = dict[key]; 
    CumulativeSize -= value.Length; 
    dict.Remove(key); 
    } 

    int CumulativeSize { public get; private set; } 
} 

यह सुंदर किसी न किसी तरह है। जाहिर है यह अधिक कुशल और अधिक मजबूत हो सकता है। मैं नहीं कर रहा हूं यह देखने के लिए Add और Remove में कोई भी जांच देखने के लिए कि कोई कुंजी पहले से मौजूद है, आदि, लेकिन मुझे लगता है कि आपको शायद यह विचार मिल जाएगा। साथ ही, यह संभव है कि शब्दकोश में मूल्यों के रूप में संग्रहीत तारों को बाहरी रूप से संशोधित किया जा सकता है (शायद आपके प्रोग्राम में नहीं, बल्कि सैद्धांतिक रूप से), इसलिए जब एक मान हटा दिया जाता है तो CumulativeSize से स्ट्रिंग की लंबाई घटा दी जाती है जब मूल रूप से जोड़ा गया था तो कैश उस स्ट्रिंग की लंबाई के समान नहीं हो सकता है। यदि यह एक चिंता है, तो आप आंतरिक शब्दकोश में मूल्यों की प्रतियों को संग्रहित करने पर विचार कर सकते हैं। मैं यह कहने के लिए आपके आवेदन के बारे में पर्याप्त नहीं जानता कि यह एक अच्छा विचार है या नहीं।

पूर्णता के लिए ...यहां एक मोटा कार्यान्वयन है जो बस एक शब्दकोश को लपेटता है, आईडीआईआर इंटरफेस का खुलासा करता है, और कैश में वस्तुओं के कुल आकार का ट्रैक रखता है। इसका आकार थोड़ा अधिक रक्षात्मक कोड है, मुख्य रूप से आकार संचयक की रक्षा के लिए। एकमात्र हिस्सा जिसे मैं मुश्किल समझ सकता हूं वह इंडेक्स सेटर है ... मेरा कार्यान्वयन यह देखने के लिए जांचता है कि इंडेक्स सेट पहले से मौजूद है या नहीं। यदि ऐसा है, तो संचयी मूल्य उचित रूप से कम किया जाता है और फिर इनपुट मान के आकार के आधार पर बढ़ाया जाता है। अन्यथा, मुझे लगता है कि यह बहुत सरल है।

public class MySpecialDictionary : IDictionary<string, string> 
    { 
    private IDictionary<string, string> dict = new Dictionary<string, string>(); 

    public int TotalSize { get; private set; } 

    #region IDictionary<string,string> Members 

    public void Add(string key, string value) 
    { 
     dict.Add(key, value); 
     TotalSize += string.IsNullOrEmpty(value) ? 0 : value.Length; 
    } 

    public bool ContainsKey(string key) 
    { 
     return dict.ContainsKey(key); 
    } 

    public ICollection<string> Keys 
    { 
     get { return dict.Keys; } 
    } 

    public bool Remove(string key) 
    { 
     string value; 
     if (dict.TryGetValue(key, out value)) 
     { 
     TotalSize -= string.IsNullOrEmpty(value) ? 0 : value.Length; 
     } 
     return dict.Remove(key); 
    } 

    public bool TryGetValue(string key, out string value) 
    { 
     return dict.TryGetValue(key, out value); 
    } 

    public ICollection<string> Values 
    { 
     get { return dict.Values; } 
    } 

    public string this[string key] 
    { 
     get 
     { 
     return dict[key]; 
     } 
     set 
     { 
     string v; 
     if (dict.TryGetValue(key, out v)) 
     { 
      TotalSize -= string.IsNullOrEmpty(v) ? 0 : v.Length; 
     } 
     dict[key] = value; 
     TotalSize += string.IsNullOrEmpty(value) ? 0 : value.Length; 
     } 
    } 

    #endregion 

    #region ICollection<KeyValuePair<string,string>> Members 

    public void Add(KeyValuePair<string, string> item) 
    { 
     dict.Add(item); 
     TotalSize += string.IsNullOrEmpty(item.Value) ? 0 : item.Value.Length; 
    } 

    public void Clear() 
    { 
     dict.Clear(); 
     TotalSize = 0; 
    } 

    public bool Contains(KeyValuePair<string, string> item) 
    { 
     return dict.Contains(item); 
    } 

    public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) 
    { 
     dict.CopyTo(array, arrayIndex); 
    } 

    public int Count 
    { 
     get { return dict.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return dict.IsReadOnly; } 
    } 

    public bool Remove(KeyValuePair<string, string> item) 
    { 
     string v; 
     if (dict.TryGetValue(item.Key, out v)) 
     { 
     TotalSize -= string.IsNullOrEmpty(v) ? 0 : v.Length; 
     } 
     return dict.Remove(item); 
    } 

    #endregion 

    #region IEnumerable<KeyValuePair<string,string>> Members 

    public IEnumerator<KeyValuePair<string, string>> GetEnumerator() 
    { 
     return dict.GetEnumerator(); 
    } 

    #endregion 

    #region IEnumerable Members 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return dict.GetEnumerator(); 
    } 

    #endregion 
    } 

शुभकामनाएँ!

+0

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

1

आपको यह बताने के लिए ढांचे में कोई विधि नहीं है कि कोई ऑब्जेक्ट कितनी मेमोरी का उपयोग कर रहा है, क्योंकि किसी भी प्रकार की वस्तु के लिए ऐसा करना बहुत जटिल होगा।

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

+0

हाँ, चाबियाँ अद्वितीय हैं। यह मेरी फॉलबैक थी कि केवल के/वी जोड़ी और स्केल के आकार का अनुमान लगाया जाए जो संग्रह के आकार के रूप में मूल्यवान था। मेरी मुख्य समस्या यह है कि जोड़ी में मान एक परिवर्तनीय लंबाई स्ट्रिंग है, और एक बार जब मैं 1 मिलियन रिकॉर्ड तोड़ता हूं तो +/- 50% विग्लू कमरा मूल्य में बड़ा हो सकता है। – kmarks2

+1

तारों के लिए स्मृति उपयोग आमतौर पर सरल होता है, लंबाई * 2 प्लस कुछ ओवरहेड (32/64 बिट प्लेटफॉर्म पर 12/20 बाइट्स डिप्लेन्डरिंग) होता है। ध्यान दें कि यदि आप 'स्ट्रिंगबिल्डर' का उपयोग करके स्ट्रिंग बनाते हैं तो स्ट्रिंग में अंत में अतिरिक्त अप्रयुक्त स्थान हो सकता है। – Guffa

+0

यह एक विचार है ... मैं इसे आज़माउंगा और देख सकता हूं कि तथ्य यह है कि 1-2 मिलियन प्रविष्टियां एक प्रदर्शन सौदा ब्रेकर है। – kmarks2

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