2009-12-23 15 views
10

त्वरित एक; क्या मैं यह सोचने में सही हूं कि 'कॉन्स्ट के रूप में' एक विधि को स्ट्रिंग पास करने से 'तार' के रूप में स्ट्रिंग को पार करने से अधिक ओवरहेड शामिल है? कंपाइलर को स्ट्रिंग की प्रतिलिपि बनाने के लिए डेल्फी मिल जाएगी और फिर स्ट्रिंग पैरामीटर को कॉन्स्ट के रूप में घोषित किया गया है, तो प्रतिलिपि पास करें, है ना?डेल्फी; पास स्ट्रिंग्स बनाम गुजर स्ट्रिंग्स का प्रदर्शन बनाम

प्रश्न का कारण थोड़ा कठिन है; हमारे पास विरासत डेल्फी 5 उपयोगिता है जिसका दिन वास्तव में गिना जाता है (प्रतिस्थापन विकास में है)। यह स्ट्रिंग प्रसंस्करण की एक बड़ी मात्रा करता है, जो अक्सर विभिन्न कार्यों और प्रक्रियाओं के बीच 1-2 केबी तारों को पार करता है। कोड के दौरान, मानकों को पार करने के लिए CONST या VAR का उपयोग करने का 'सही' अवलोकन (हाथ में नौकरी के आधार पर) का पालन किया गया है। हम केवल कुछ 'त्वरित जीत' की तलाश में हैं जो नए संस्करण तैयार होने तक हमें ज्वार करने के लिए निष्पादन समय से कुछ माइक्रोसेकंड दाढ़ी दे सकते हैं। हमने डिफॉल्ट डेल्फी 5 से फास्टएमएम में मेमोरी मैनेजर को बदलने का विचार किया, और हमने यह भी सोचा कि क्या तारों को पार करने के तरीके को बदलने में लायक है - क्योंकि कोड कॉन्स के रूप में पारित तारों के साथ ठीक काम कर रहा है, हम नहीं करते हैं एक समस्या देखें यदि हमने उन घोषणाओं को var में बदल दिया - उस विधि के भीतर कोड स्ट्रिंग को बदलने वाला नहीं है।

लेकिन क्या वास्तव में वास्तविक शर्तों में कोई अंतर आएगा? (कार्यक्रम वास्तव में इन 1kb + ish तारों पर बड़ी मात्रा में प्रसंस्करण करता है; कई सौ स्ट्रिंग एक मिनट में चोटी के समय)। फिर से लिखने में इन तारों को ऑब्जेक्ट्स/क्लास वेरिएबल्स में रखा जा रहा है, इसलिए उन्हें वास्तव में उसी तरह से कॉपी/पास नहीं किया जा रहा है, लेकिन विरासत कोड में यह बहुत पुराना स्कूल 'पास्कल है।

स्वाभाविक रूप से हम कार्यक्रम के एक समग्र भाग को देखने के लिए देखेंगे कि हमने क्या अंतर बनाया है, लेकिन वास्तव में यह कोशिश करने में कोई बात नहीं है कि अगर हम पहले उदाहरण में स्ट्रिंग-पासिंग कैसे काम करते हैं, तो हम स्पष्ट रूप से गलत हैं!

+0

भी देखें: [? स्थिरांक लकीर का फकीर बना या तर्कसंगत के उपयोग है] (http://stackoverflow.com/questions/5844904/is-the-use -of-const-dogmatic-or-rational) – NGLN

उत्तर

12

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

procedure TForm1.Button1Click(Sender: TObject); 
var 
    s: string; 
begin 
    s := 'foo bar baz'; 
    UniqueString(s); 
    SetConstCaption(s); 
    Caption := s; 
end; 

procedure TForm1.SetConstCaption(const AValue: string); 
var 
    P: PChar; 
begin 
    P := PChar(AValue); 
    P[3] := '?'; 
    Caption := AValue; 
end; 

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

लेकिन निश्चित रूप से FastMM4 का उपयोग करें, इसका बहुत बड़ा प्रदर्शन प्रभाव होना चाहिए।

+0

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

+7

एक var स्ट्रिंग पैरामीटर वास्तव में स्ट्रिंग वेरिएबल को पॉइंटर पास करता है, जबकि एक कॉन्स स्ट्रिंग पैरामीटर बस स्ट्रिंग वैल्यू को पास करता है। इस प्रकार Var में संकेत की एक अतिरिक्त परत है, इसलिए यह कॉन्स की तुलना में धीमी होनी चाहिए। –

+1

?? यह मुझे समझ में नहीं आता है। मैंने हमेशा सोचा कि (लंबे) स्ट्रिंग हमेशा संदर्भ (सूचक) द्वारा पारित किया गया था। यदि चिह्नित * कॉन्स * या * var * तो यह पारित स्ट्रिंग के लिए एक सूचक है, यदि चिह्नित नहीं किया गया है * या तो * const * या * var, तो साइड इफेक्ट्स से बचने के लिए एक प्रतिलिपि बनाई जाती है यदि नियमित स्ट्रिंग पैरामीटर को संशोधित करता है और पॉइंटर होता है प्रतिलिपि के लिए। एकमात्र कारण है कि मैं * var * स्ट्रिंग पैरा को * कॉन्स * की तुलना में केवल बहुत ही मामूली रूप से धीमा होने की अपेक्षा करता हूं कि एक * var * स्ट्रिंग param संभवतः उस कॉल के लिए उत्पन्न प्रगा में संदर्भ गिनती है जो * कॉन्स * स्ट्रिंग पैरामीटर। – Deltics

3

const afaik का उपयोग करते समय संकलक स्ट्रिंग की एक प्रति नहीं बनायेगा। const का उपयोग करके आप जिस स्ट्रिंग का उपयोग करते हैं, उसके लिए रिफाउंटर को बढ़ाने/घटाने का ओवरहेड बचाता है।

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

+0

धन्यवाद, The_Fox। हम पहले से ही एक अधिक अनुकूलित स्ट्रिंग हैंडलिंग इकाई (हाइपरस्ट्रिंग का हिस्सा) का उपयोग कर रहे हैं और जो मैंने त्वरित Google के माध्यम से एकत्र किया है, फास्टकोड प्रोजेक्ट वेब पेज नीचे/चला गया प्रतीत होता है, और अन्य मुख्य फास्टकोड पृष्ठ पर दिए गए नोट्स का अर्थ है कि डेल्फी 5 समर्थित नहीं है। फिर भी, मुझे लगता है कि मैं फास्टकोड को हमारे डेल्फी 7 अनुप्रयोगों के लिए देखे जाने योग्य कुछ के रूप में चिह्नित करूंगा यदि समय आता है। मैं निश्चित रूप से फास्टएमएम 4 प्लग-इन करूँगा। धन्यवाद! – robsoft

2

Const पहले से ही किसी फ़ंक्शन पर पैरामीटर पास करने का सबसे प्रभावी तरीका है। यह एक प्रतिलिपि (डिफ़ॉल्ट, मूल्य से) बनाने या यहां तक ​​कि एक सूचक (var, संदर्भ द्वारा) गुजरने से बचाता है।
यह तारों के लिए विशेष रूप से सच है और वास्तव में जाने का तरीका था जब कंप्यूटिंग शक्ति सीमित थी और बर्बाद नहीं होती थी (इसलिए "पुराना स्कूल" लेबल)।

आईएमओ, const डिफ़ॉल्ट सम्मेलन होना चाहिए, प्रोग्रामर तक इसे बदलने के लिए वास्तव में मूल्य या var द्वारा आवश्यक होने पर इसे बदलने के लिए होना चाहिए।यह पास्कल की समग्र सुरक्षा (पैर में खुद को शूटिंग के अवसर को सीमित करने के रूप में सीमित) के अनुरूप होगा।

मेरे 2 ¢ ...

9

const डेल्फी में मापदंडों के लिए अनिवार्य रूप से मतलब "मैं इस, उत्परिवर्तित करने के लिए नहीं जा रहा हूँ और मैं भी परवाह नहीं है इस मूल्य द्वारा या संदर्भ से पारित हो जाता है - जो भी सबसे कुशल है वह मेरे द्वारा ठीक है "। बोल्ड हिस्सा महत्वपूर्ण है, क्योंकि यह वास्तव में देखने योग्य है। इस कोड पर विचार करें:

type TFoo = 
    record 
    x: integer; 
    //dummy: array[1..10] of integer; 
    end; 

procedure Foo(var x1: TFoo; const x2: TFoo); 
begin 
    WriteLn(x1.x); 
    WriteLn(x2.x); 

    Inc(x1.x); 
    WriteLn; 

    WriteLn(x1.x); 
    WriteLn(x2.x); 
end; 

var 
    x: TFoo; 
begin 
    Foo(x, x); 
    ReadLn; 
end. 

यहाँ चाल, कि हम एक ही चर पारित दोनों var के रूप में और const के रूप में है ताकि हमारे समारोह एक तर्क के माध्यम से उत्परिवर्तित कर सकते हैं, और देखने के लिए अगर यह अन्य प्रभावित करता है। यदि आप उपरोक्त कोड के साथ प्रयास करते हैं, तो आप देखेंगे कि Foo के अंदर x2.x नहीं बदलता है, इसलिए x2 मूल्य से पारित किया गया था। लेकिन TFoo में सरणी घोषणा को असम्बद्ध करने का प्रयास करें, ताकि उसका आकार बड़ा हो जाए और इसे फिर से चलाया जा सके - और आप देखेंगे कि x2.x अब x1.x उपनाम है, इसलिए हमारे पास अब x2 के लिए पास-बाय-रेफरेंस है!

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

4

यह वास्तव में एक टिप्पणी है, लेकिन एक लंबा मेरे साथ सहन करता है।

के बारे में 'तथाकथित' स्ट्रिंग गुजर मूल्य

डेल्फी द्वारा हमेशाstring और ansistring(WideStrings और ShortStrings छोड़कर) संदर्भ द्वारा गुजरता है, सूचक के रूप में।
तो तार कभी भी मूल्य से पारित नहीं होते हैं।
यह आसानी से 100 एमबी तारों को पारित करके परीक्षण किया जा सकता है।

जब तक आप उन्हें बुलाया दिनचर्या स्ट्रिंग गुजर के शरीर के अंदर परिवर्तन नहीं करते के रूप में लेता है हे (1) समय

हालांकि (और उस पर एक छोटा सा निरंतर के साथ) जब var बिना एक स्ट्रिंग गुजर या const खंड, डेल्फी तीन चीजें करता है।

  1. स्ट्रिंग की संदर्भ संख्या बढ़ाएं।
  2. प्रक्रिया के चारों ओर एक निहित प्रयास अंततः ब्लॉक डालें, इसलिए स्ट्रिंग पैरामीटर की संदर्भ संख्या घट जाती है।
  3. जब स्ट्रिंग बदल जाती है (और केवल तभी) डेल्फी स्ट्रिंग की एक प्रति बनाता है, पारित स्ट्रिंग की संदर्भ संख्या कम कर देता है और शेष दिनचर्या में प्रति का उपयोग करता है।
    यह करने में यह pass by value बनाता है।संदर्भ गिनती

    1. :

    संदर्भ द्वारा गुजर (सूचक)

    स्ट्रिंग एक const या var के रूप में पारित हो जाता है जब के बारे में, डेल्फी भी एक संदर्भ (सूचक) से गुजरता है, लेकिन स्ट्रिंग का नहीं बढ़ता है। (छोटी, छोटी गति वृद्धि)

  4. कोई अंतर्निहित प्रयास/आखिरकार दिनचर्या के आसपास नहीं रखा जाता है, क्योंकि इसकी आवश्यकता नहीं होती है। यह भाग 1 है क्यों const/var स्ट्रिंग पैरामीटर तेजी से निष्पादित करते हैं।
  5. जब नियमित रूप से स्ट्रिंग बदल जाती है, कोई प्रतिलिपि वास्तविक स्ट्रिंग बदल जाती है। const पैरामीटर के लिए संकलक स्ट्रिंग विकल्पों को प्रतिबंधित करता है। यह भाग 2 है क्यों var/const स्ट्रिंग पैरामीटर तेजी से काम करते हैं।
  6. यदि हालांकि आपको स्ट्रिंग को असाइन करने के लिए स्थानीय var बनाने की आवश्यकता है; डेल्फी स्ट्रिंग :-) की प्रतिलिपि बनाता है और const स्ट्रिंग पैरामीटर की गति लाभ के 99% + को समाप्त करने के लिए एक निहित प्रयास/अंत में अवरुद्ध करता है।

आशा है कि इस मुद्दे पर कुछ प्रकाश डालें।
अस्वीकरण: इस जानकारी के अधिकांश here, here और here से आता है

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