2012-08-15 8 views
5

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

प्रोटोबफ-नेट का उपयोग करके एक उच्च-थ्रूपुट परिदृश्य में, जहां बहुत से आवंटन एक समस्या है (विशेष रूप से जीसी के लिए), क्या ऑब्जेक्ट का पुन: उपयोग करना संभव है? उदाहरण के लिए Clear() विधि जोड़कर?

[ProtoContract] 
public class MyDTO 
{ 
    [ProtoMember(1)] 
    public int Foo { get; set; } 
    [ProtoMember(2)] 
    public string Bar { get; set; } 
    [ProtoMember(3, DataFormat = DataFormat.Group)] 
    public List<int> Values { get { return values; } } 
    private readonly List<int> values = new List<int>(); 

    public void Clear() 
    { 
     values.Clear(); 
     Foo = 0; 
     Bar = null; 
    } 
} 

उत्तर

6

Protobuf शुद्ध अपने Clear() विधि ही कॉल करेंगे कभी नहीं, लेकिन साधारण मामलों के लिए आप बस अपने आप ऐसा कर सकते हैं, और (v1 एपीआई पर Merge विधि का उपयोग करें, या बस v2 में Deserialize में वस्तु पारित एपीआई)। उदाहरण के लिए:

MyDTO obj = new MyDTO(); 
for(...) { 
    obj.Clear(); 
    Serializer.Merge(obj, source);   
} 

यह मौजूदाobj के बजाय एक नई वस्तु हर बार बनाने में डेटा लोड करता है।

अधिक जटिल स्थितियों जहां वस्तु आवंटन, की संख्या को कम करना चाहते हैं और अपने आप को संभालने के लिए वस्तु पूलिंग/पुनः उपयोग करने खुश हैं, फिर आप एक कस्टम कारखाने का उपयोग कर सकते हैं। उदाहरण के लिए, आप के लिए MyDTO जैसे एक विधि जोड़ सकते हैं:

// this can also accept serialization-context parameters if 
// you want to pass your pool in, etc 
public static MyDTO Create() 
{ 
    // try to get from the pool; only allocate new obj if necessary 
    return SomePool.GetMyDTO() ?? new MyDTO(); 
} 

और, एप्लिकेशन-स्टार्टअप पर, कॉन्फ़िगर Protobuf शुद्ध इसके बारे में पता करने के लिए:

RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create"); 

(SetFactory भी एक MethodInfo स्वीकार कर सकते हैं - उपयोगी है अगर फैक्ट्री विधि को प्रकार के अंदर घोषित नहीं किया गया है)

इसके साथ, कारखाना विधि का उपयोग सामान्य निर्माण के बजाय किया जाना चाहिए तंत्र। हालांकि, यह पूरी तरह से आपकी नौकरी को साफ करने के लिए रहता है (Clear()) ऑब्जेक्ट्स जब आप उनके साथ समाप्त होते हैं, और उन्हें अपने पूल में वापस लौटते हैं। कारखाने के दृष्टिकोण के बारे में विशेष रूप से अच्छा क्या है कि यह सूचियों, आदि में नए उप-वस्तुओं के लिए काम करेगा, जो आप Merge से नहीं कर सकते हैं।

+0

हाय मार्क, अगर मैं साफ़() विधि को लागू नहीं करता तो क्या होता है? क्या सभी फ़ील्ड वैसे भी ओवरराइट हो जाएंगे? – driAn

+1

@driAn केवल इनबाउंड स्ट्रीम में डेटा वाले फ़ील्ड असाइन किए जाएंगे। यदि आप एक कस्टम कारखाने का उपयोग करते हैं जो उदाहरणों को पुन: पेश करता है, तो आपको कारखाने के अंदर अपना खुद का रीसेट कोड प्रदान करना चाहिए। यदि आप कस्टम फैक्ट्री का उपयोग नहीं कर रहे हैं तो यह कोई समस्या नहीं है –

+0

हाय मार्क, मैं उपरोक्त विधि Deserialize() को ऑब्जेक्ट इंस्टेंस के साथ भरने/विलय करने के लिए देख रहा हूं। लेकिन मुझे यह नहीं मिला। मुझे केवल एक विधि मिलती है: Serializer.Deserialize (स्ट्रीम)। क्या भरने के लिए ऑब्जेक्ट इंस्टेंस निर्दिष्ट करने का अभी भी कोई तरीका है? मैं ऑब्जेक्ट पूल से वस्तुओं का पुन: उपयोग करना चाहता हूं और इस तरह से एक कस्टम फैक्ट्री के साथ दूसरे तरीके से निपटना आसान लगता है ... अग्रिम धन्यवाद। –

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

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