2012-02-23 30 views
8

मेरे पास ऑब्जेक्ट्स का संग्रह है और मैं इस संग्रह को क्लोन करने और विभिन्न दृष्टिकोणों के प्रदर्शन निहितार्थ को समझने की कोशिश कर रहा हूं।डीपक्लोन का प्रदर्शन (बाइनरी सीरियलाइजेशन का उपयोग करके) मैन्युअल रूप से गुणों को सेट करना

संग्रह में ऑब्जेक्ट में लगभग 20 गुण हैं, सभी तार, इंट्स, फ्लोट्स (इस ऑब्जेक्ट में इसके अंदर कोई नेस्टेड ऑब्जेक्ट नहीं है)। दो दृष्टिकोण हैं:

  1. DeepClone() विधि बनाएं:

    public static class ExtensionMethods 
    { 
        public static T DeepClone<T>(this T a) 
        { 
         using (var stream = new MemoryStream()) 
         { 
          var formatter = new BinaryFormatter(); 
          formatter.Serialize(stream, a); 
          stream.Position = 0; 
          return (T)formatter.Deserialize(stream); 
         } 
        } 
    

    }

  2. मैन्युअल बारे में "कॉपी" कोड जहां मैं संग्रह के माध्यम से पाशन कर रहा हूँ और 'नई' एक ing नई वस्तु और फिर मैन्युअल रूप से सभी 20 गुणों को सेट करना। इस

    public MyObject Copy(MyObject myObj) 
    { 
    var obj = new MyObject(); 
    obj.Prop1 = myObj.Prop1; 
    obj.Prop2 = myObj.Prop2; 
    return obj; 
    

    }

की तरह कुछ मैं बहुत असंगत परिणाम हो रही है तो मैं पर लोगों प्रतिक्रिया प्राप्त करना चाहता था:

  1. एक बहुत तेजी से अन्य है कि हो सकता है? मैंने दो विकल्प सोचा होगा लेकिन मेरे परीक्षण इस तरह का समर्थन नहीं करते हैं इसलिए मैं यह पता लगाने की कोशिश कर रहा हूं कि मैं कुछ गलत कर रहा हूं।

  2. क्या यह और भी तेज़ करने का कोई तरीका है?

+0

मुझे यकीन नहीं है कि आपने इस दीपक्लोन() को लेबल क्यों किया है, जब आप केवल उथली प्रतिलिपि करना चाहते हैं। चूंकि तार अपरिवर्तनीय हैं, इसलिए स्ट्रिंग की एक उथली प्रति एक गहरी प्रति के बराबर होती है। इसके अलावा, मैन्युअल सेटिंग बहुत तेजी से होनी चाहिए क्योंकि बाइनरीफॉर्मेटर संपत्ति नाम, सेटर्स, कन्स्ट्रक्टर इत्यादि प्राप्त करने के लिए प्रतिबिंब का उपयोग करता है। – Gleno

+0

@ गेलनो - यह विधि गहराई से ऑब्जेक्ट क्लोन करेगी यदि उसके अंदर नेस्टेड ऑब्जेक्ट्स (इस प्रकार नाम) – leora

उत्तर

5

ठीक है, सबसे पहले बाइनरीफॉर्मेटर मार्ग निश्चित रूप से धीमा होना चाहिए, क्योंकि यह गुणों को प्राप्त/सेट करने के लिए प्रतिबिंब का उपयोग करता है। सबसे आम विधि आईसीएलएबल इंटरफेस का उपयोग एक प्रतिलिपि निर्माता के साथ संयोजन में कर रही है।

class A : ICloneable 
{ 
    private readonly int _member; 

    public A(int member) 
    { 
     _member = member; 
    } 

    public A(A a) 
    { 
     _member = a._member; 
    } 

    public object Clone() 
    { 
     return new A(this); 
    } 
} 

बेशक आपको कड़ाई से बोलने के लिए केवल कॉपी कन्स्ट्रक्टर की आवश्यकता है, जो सबसे तेज़ तरीका होना चाहिए। यदि आपकी ऑब्जेक्ट सरल हैं, तो आपको इन-निर्मित MemberwiseClone फ़ंक्शन का उपयोग करने का प्रयास करना चाहिए।

class A : ICloneable 
{ 
    private readonly int _member; 

    public A(int member) 
    { 
     _member = member; 
    } 

    public object Clone() 
    { 
     return MemberwiseClone(); 
    } 
} 

इस बीच, मैं some test code लिखा था देखने के लिए अगर MemberwiseClone() गंभीर रूप से था तेजी से या एक प्रति निर्माता का उपयोग कर की तुलना में धीमी। आप इसे here पा सकते हैं। मैंने पाया कि सदस्यवाक्लोन कम से कम छोटे वर्गों पर, कॉपीकॉन्स्ट्रक्टर करने से वास्तव में बहुत धीमी है। ध्यान दें कि बाइनरीफॉर्मेटर का उपयोग करना बेहद धीमा है।

+0

नहीं है सदस्यवृत्ति का उपयोग प्रतिबिंब का उपयोग करें? या यह सिर्फ एक गड़बड़ है, और जीसी को और सहायता की आवश्यकता नहीं है? – zmbq

+0

मुझे लगता है कि यह प्रदर्शन प्राप्त करने के लिए कुछ सीएलआर हुक का उपयोग करता है, इसलिए मूल रूप से memcpy और कुछ समायोजन। – Gleno

+0

सदस्यwiseक्लोन के लिए सहायता के रूप में यह उल्लेख किया गया है कि यह एक उथली प्रतिलिपि बनाता है यह बाइनरीफॉर्मेटर का उपयोग करने जैसा ही हो सकता है? मुझे संदेह है क्योंकि उस समारोह को दीपकोपी नाम दिया गया है, जो मुझे लगता है कि नाम गलत है। मेरा मुद्दा यह है कि गहरे क्लोन को संदर्भित वस्तुओं को भी क्लोन करना चाहिए ??? – 000

0

इसके लिए क्रमबद्धता का उपयोग करना एक बहुत चालाक विचार है। हालांकि, गुणों को एक-एक करके सेट करना उतना तेज़ होना चाहिए, और अधिकांश समय (जब वस्तुएं वास्तव में छोटी होती हैं) को तेज़ी से करना चाहिए - आप कम काम कर रहे हैं, और प्रतिबिंब का उपयोग नहीं कर रहे हैं।

क्या आप ऐसे मामले को पुन: पेश कर सकते हैं जहां धारावाहिकता का उपयोग करके 'हाथ से गुणों की प्रतिलिपि बनाने की तुलना में तेज़ था?

0

सीरियलाइजेशन निश्चित रूप से धीमा हो तो संपत्ति संपत्ति असाइनमेंट हो।

बाइनरी क्रमबद्धता बेहतर है, क्योंकि कोड आसान और बनाए रखने में आसान है।

क्लोन के दौरान संपत्ति असाइनमेंट बेहतर कारण हो सकता है, आप ऑब्जेक्ट के सभी क्लोन नहीं करना चाहते हैं, लेकिन रास्ते में उन्हें क्रमबद्ध करने में सक्षम होना चाहते हैं। संक्षेप में आप प्रवाह पर अधिक नियंत्रण रखते हैं।

2

मेरी पिछली भूमिका में, हमने इस मुद्दे की जांच की, क्योंकि हम वस्तुओं को कैश कर रहे थे और उन्हें कैश से बाहर करने से पहले उन्हें क्लोन करना चाहते थे।

हम कुछ विस्तृत बेंच मार्किंग किया और पाया कि संपत्ति की स्थापना, तेजी से हमेशा कम से कम परिमाण के एक आदेश तो BinaryFormatter दृष्टिकोण था के रूप में बहुत सरल BinaryFormatter दृष्टिकोण करने का विरोध किया है, हालांकि स्पष्ट रूप से एक हाथ से लुढ़का कार्यान्वयन की आवश्यकता है। गहरे ऑब्जेक्ट ग्राफ के लिए, अंतर आईआईआरसी अधिक स्पष्ट हो गया।

अंत में, हम एक तीन आयामी दृष्टिकोण पर बसे करने के लिए "क्लोनिंग":

  • यदि प्रकार अपरिवर्तनीय (जिसे हम, एक मार्कर इंटरफेस के साथ सूचित करेंगे IImutable था, लेकिन आप समान रूप से एक विशेषता इस्तेमाल कर सकते हैं या somesuch), हम मूल उदाहरण लौटकर "क्लोन" करेंगे। चूंकि हम जानते थे कि कोई भी इसे बदल नहीं सकता है, वही उदाहरण लौटने के लिए सुरक्षित था। जाहिर है यह "क्लोन" का सबसे तेज़ प्रकार था, हालांकि स्पष्ट रूप से वास्तव में एक क्लोन बिल्कुल नहीं था।
  • यदि इस प्रकार ने अपना IDeepCloneable<T> इंटरफ़ेस लागू किया (जो आपके दूसरे उदाहरण की तरह होगा - लेकिन जेनेरिक) हम इसका उपयोग करेंगे। [यह सामान्य इंटरफ़ेस गैर-जेनेरिक समतुल्य IDeepCloneable]
  • से प्राप्त होगा, यह आपके पहले उदाहरण, BinaryFormatter पर वापस आ जाएगा।

मैं "अपरिवर्तनीय" दृष्टिकोण का उल्लेख आप क्या कर रहे हैं पर निर्भर करता है, कभी कभी सबसे अच्छा तरीका कक्षाएं आप क्लोन करने की जरूरत है ताकि वे क्लोन करने की आवश्यकता नहीं है नया स्वरूप है, क्योंकि। अगर वे अनिवार्य रूप से केवल एक बार बनाए जाते हैं, तो यह आसान है; लेकिन यदि नहीं, तो कभी-कभी निर्माता/अपरिवर्तनीय प्रकार का दृष्टिकोण उपयोगी होता है (ढांचे में Uri बनाम UriBuilder देखें। पूर्व अनिवार्य रूप से अपरिवर्तनीय है, जबकि उत्तरार्द्ध का उपयोग पूर्व के उदाहरणों को बनाने और/या उत्परिवर्तित करने के लिए किया जा सकता है)।

0

सभी दृष्टिकोण मानते हैं 1) धारावाहिक और 2) सरल (पर्याप्त) वस्तुओं। यदि आपके पास ऑब्जेक्ट्स हैं जिनमें हैशटेबल्स हो सकते हैं जिसमें हैशटेबल्स हो सकते हैं, गहराई पर कोई लागू सीमा नहीं है, तो आपको कुछ रिकर्सिव ऑब्जेक्ट क्रॉलिंग के बिना आपके हाथों पर गड़बड़ हो गई है।

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

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