2011-10-17 21 views
8

मुझे अपने नियंत्रण में सीमित संख्या में कक्षाओं के लिए पूर्ववत + फिर से स्टैक करना होगा, जो बहुत तेज़ होना चाहिए और आरटीटीआई और एक्सएमएल या धाराओं का उपयोग करना संभव नहीं है क्योंकि उदाहरणों की गिनती 2000+ के बराबर हो सकती है नेस्टेड ऑब्जेक्ट सूचियां। वस्तुओं को स्मृति चिन्ह के माध्यम से अंदर और बाहर कॉपी करने की आवश्यकता है और तुरंत पुनः लोड किया जाना चाहिए।क्या मैं अपनी याददाश्त की प्रतिलिपि बनाकर किसी ऑब्जेक्ट को क्लोन कर सकता हूं?

क्या मेमोरी की प्रतिलिपि बनाकर ऑब्जेक्ट क्लोन करने और उस स्मृति से वस्तुओं को फिर से चालू करने का कोई तरीका है?

+1

तो आप वस्तुओं को क्लोन किए बिना स्मृति चिन्ह को कार्यान्वित नहीं कर सकते? क्या आपके सभी ऑब्जेक्ट्स टीपीर्सिस्टेंट से विरासत में हैं, और इस प्रकार टीपीर्सिस्टेंट का समर्थन करते हैं। साइन इन आपकी सबसे अच्छी शर्त है? –

+0

आप तब तक ऐसा कर सकते थे जब आपकी वस्तुओं में संदर्भ नहीं थे। –

+1

समस्या यह है कि ऑब्जेक्ट इसकी स्मृति से अधिक है। खुली फाइलों, अन्य हैंडल, सिंक्रनाइज़ेशन प्राइमेटिव्स, रीफ्रैंटिंग के साथ इंटरफेस इत्यादि के बारे में क्या? केवल वस्तु ही जानता है कि खुद को सही तरीके से कैसे कॉपी करें। – haimg

उत्तर

15

शायद ही कभी। आप किसी ऑब्जेक्ट की स्मृति को आसानी से कॉपी कर सकते हैं, लेकिन उस मेमोरी का हिस्सा पॉइंटर्स होगा, जिस स्थिति में आप केवल संदर्भ की प्रतिलिपि बनाते हैं। उन पॉइंटर्स में स्ट्रिंग्स और अन्य ऑब्जेक्ट्स भी शामिल हो सकते हैं।

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

3

एक वस्तु क्लोन करने के लिए एक आसान तरीका है:

  • से अपने clonable वर्ग प्राप्त TPersistent
  • लागू असाइन प्रक्रिया

मेमेंटो देखें डिज़ाइन पैटर्न यहाँ उदाहरण: http://sourcemaking.com/design_patterns/memento/delphi/1

+0

स्रोतmaking.com – MX4399

+0

thx का उल्लेख करने के लिए 10 अंक! स्रोत निर्माण हमेशा एक अच्छा संदर्भ है। – TridenT

0

पूर्ववत/फिर से TMEMoryStream के साथ कार्यान्वित किया जा सकता है - बस ऑब्जेक्ट के डेटा को स्ट्रीम करने के लिए सहेजें और इसे फिर से लोड होने पर लोड करें। यह ऑब्जेक्ट की सेव टॉस्ट्रीम/लोडफ्रॉस्ट्रीम मैकेनिक्स का उपयोग करता है और संदर्भों को सही तरीके से पुनर्निर्माण करने की अनुमति देता है।

अद्यतन:

TMyObject = class 
    procedure SaveToStream(AStream : TStream); 
    procedure LoadFromStream(AStream : TStream); 
end; 

तब:

में बदलाव से पहले:

myobject.SaveToStream(MemoryStream); 
undoManager.AddItem(myobject.Identifier, MemoryStream); 
Do change object... 

तक बहाल

myobject := FindObject(undomanager.LastItem.Identifier) 
myobject.LoadFromStream(undomanager.LastItem.MemoryStream); 

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

+2

टॉब्जेक्ट में SaveToStream नहीं है। –

+0

मेरा मतलब टॉब्जेक्ट नहीं था, मुझे पता है कि इसमें कोई दृढ़ता कार्य नहीं है। – George

+1

फिर * क्या मतलब है? अधिक सटीक होने के लिए कृपया अपना उत्तर संपादित करें। आपने वाक्य के मध्य में * ऑब्जेक्ट * को कैपिटल किया है, जिसका सुझाव है कि आप 'TObject' का मतलब है। यदि आपके लिए उचित संज्ञा होने का मतलब नहीं था, तो आपको इसके सामने एक लेख (यानी, * एक * या * *) की भी आवश्यकता है। –

10

2000+ नेस्टेड ऑब्जेक्ट्स इतना बड़ा नहीं है, और आरटीटीआई (डिस्क एक्सेस या संपीड़न बहुत धीमा हो जाएगा) के साथ भी धीमा नहीं होगा। सीधे SaveToStream मैन्युअल क्रमबद्धता के साथ, यदि आप FastMM4 (डेल्फी 2006 के बाद से डिफ़ॉल्ट मेमोरी प्रबंधक) का उपयोग करते हैं, तो यह बहुत तेज़ है।

शायद आप अपना एल्गोरिदम बदल सकते हैं और इसके बजाय गतिशील सरणी का उपयोग कर सकते हैं (एक ओपन सोर्स सीरिएलाइज़र here है)। लेकिन आपका डेटा इस तरह के रिकॉर्ड फिट नहीं हो सकता है।

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

आप string वस्तुओं के अंदर है, तो आप उन्हें पुनः आवंटित नहीं हो सकता और इस्तेमाल किया तार के एक वैश्विक सूची बनाए रखने: संदर्भ गिनती और कॉपी-ऑन-राइट यह बहुत मानक क्रमबद्धता और आवंटन (यहां तक ​​कि FastMM4 के साथ) की तुलना में तेजी कर देगा।

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

बहुत जल्दी अनुकूलित न करें। "इसे तेज़ी से बनाने से पहले इसे सही बनाएं। इसे तेज़ी से बनाने से पहले इसे साफ़ करें। इसे सही बनाते समय इसे सही रखें।" - केर्निगन और प्लोगर, प्रोग्रामिंग स्टाइल के तत्व।

+1

+1। –

+0

अंतर्दृष्टि के लिए धन्यवाद। क्लोन और असाइन करने के दृष्टिकोण का उपयोग करना सीधे मेमोरी मैनेजर पर भरोसा करता है, जैसा कि आपने बताया है - मुख्य भाग मेमोरी मैनेजर पर ध्यान केंद्रित कर रहा है और क्लोन के रूप में क्लोन को ध्वजांकित करके क्लोन को ध्वजांकित करके बुद्धिमान तरीके से ले रहा है आंतरिक रूप से और आरटीटीआई से बचें। – MX4399

+0

@ एमएक्स 439 9 वैश्विक 'स्ट्रिंग' सूची को आजमाने के लायक भी हो सकता है: संदर्भ गणना का उपयोग करके स्ट्रीम-दृष्टिकोण से निश्चित रूप से तेज़ हो सकता है। बेशक, 'असाइन()' दृष्टिकोण एक ही संदर्भ-गिनती तंत्र के फायदे का उपयोग करेगा। –

1

अतीत में इस स्थिति के लिए मैंने जिस दृष्टिकोण का उपयोग किया है, वह उस वस्तु के हिस्से के साथ एक रिकॉर्ड घोषित करना है जिसे मुझे बनाए रखने की आवश्यकता है, और उस रिकॉर्ड को कक्षा के भीतर उपयोग करें। उदाहरण के लिए Optimizing Class Size in Delphi. Is there something like "packed classes"? पर मेरा पुराना उत्तर देखें।

चूंकि रिकॉर्ड असाइनमेंट पर कॉपी किए जाते हैं, तो फ़ील्ड को एक ऑब्जेक्ट प्रकार से दूसरे में कॉपी करना आसान होता है।

उदा।

TMyFields = record 
    ID: Integer; 
    Name: string; 
end; 

TMyClass = class(TPersistent)  
private 
    FFields: TMyFields; 
    FStack: TStack; 
    class TStackItem = class(TObject) 
    public 
    Fields: TMyFields; 
    end; 

protected 
    property ID: integer read FFields.ID; 
    property Name: string read FFields.Name; 
    procedure Push; 
    // etc... 
end; 


procedure TMyClass.Push; 
var 
    NewItem: TStackItem; 
begin 
    NewItem := TStackItem.Create; 
    NewItem.Fields := FFields; 
    FStack.Push(NewItem); 
end; 
बेशक

, जैसा कि आप XE उपयोग कर रहे हैं, तो आप Generics.Collections.TObjectStack बजाय इस्तेमाल कर सकते हैं।

+0

बहुत ही रोचक दृष्टिकोण – MX4399

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