2016-03-11 5 views
5

मैं अपने प्रोजेक्ट में एक बहुत में इस्तेमाल करते हैं और मैं इन चेतावनियों के बहुत सारे है:CharInSet IN से बहुत धीमी है, क्या मुझे W1050 चेतावनी संकेत को ठीक करना चाहिए?

[डीसीसी चेतावनी] Unit1.pas (40): W1050 WideChar सेट भाव में बाइट चार को कम कर दिया। SysUtils इकाई में CharInSet फ़ंक्शन का उपयोग करने पर विचार करें।

if s1[i] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] then 

बनाम

if CharInSet(s1[i], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']) then 

यहाँ 2 परीक्षण, एक काम करता है के लिए कोड है:

मैं एक त्वरित परीक्षण और में के बजाय CharInSet उपयोग कर रहा है 65% से -100% धीमी कर दिया छोटे तारों के माध्यम से लूप के साथ, एक बार एक बड़ी स्ट्रिंग के माध्यम से एक लूप:

फ़ॉर्म पर 2 बटन जोड़कर मैंने इसे छोटी स्ट्रिंग के लिए परीक्षण किया:

procedure TForm1.Button1Click(Sender: TObject); 
var s1: string; 
    t1, t2: TStopWatch; 
    a, i, cnt, vMaxLoop: Integer; 
begin 
    s1 := '[DCC Warning] Unit1.pas(40): W1050 WideChar reduced to byte char in set expressions. Consider using CharInSet function in SysUtils unit.'; 
    vMaxLoop := 10000000; 

    cnt := 0; 
    t1 := TStopWatch.Create; 
    t1.Start; 
    for a := 1 to vMaxLoop do 
    for i := 1 to Length(s1) do 
     if s1[i] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] then 
     inc(cnt); 
    t1.Stop; 

    cnt := 0; 
    t2 := TStopWatch.Create; 
    t2.Start; 
    for a := 1 to vMaxLoop do 
    for i := 1 to Length(s1) do 
     if CharInSet(s1[i], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']) then 
     inc(cnt); 
    t2.Stop; 

    Button1.Caption := inttostr(t1.ElapsedMilliseconds) + ' - ' + inttostr(t2.ElapsedMilliseconds); 
end; 

और इस के लिए 1 लंबी स्ट्रिंग:

procedure TForm1.Button2Click(Sender: TObject); 
var s1: string; 
    t1, t2: TStopWatch; 
    a, i, cnt, vMaxLoop: Integer; 
begin 

    s1 := '[DCC Warning] Unit1.pas(40): W1050 WideChar reduced to byte char in set expressions. Consider using CharInSet function in SysUtils unit.'; 
    s1 := DupeString(s1, 1000000); 
    s1 := s1 + s1 + s1 + s1; // DupeString is limited, use this to create longer string 

    cnt := 0; 
    t1 := TStopWatch.Create; 
    t1.Start; 
    for i := 1 to Length(s1) do 
    if s1[i] in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] then 
     inc(cnt); 
    t1.Stop; 

    cnt := 0; 
    t2 := TStopWatch.Create; 
    t2.Start; 
    for i := 1 to Length(s1) do 
    if CharInSet(s1[i], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']) then 
     inc(cnt); 
    t2.Stop; 

    Button2.Caption := inttostr(t1.ElapsedMilliseconds) + ' - ' + inttostr(t2.ElapsedMilliseconds); 
end; 

वे धीमी विकल्प क्यों की सिफारिश करते हैं, या कैसे मैं प्रदर्शन में दंड के बिना इस चेतावनी को ठीक कर सकते हैं?

+2

http://stackoverflow.com/questions/332948/why-is-charinset-faster-than-case-statement – RBA

+0

पर एक नज़र डालें, मैंने उस प्रश्न को देखा, लेकिन इसे शीर्षक के कारण खारिज कर दिया - सबकुछ रेड नहीं कर सकता । लेकिन, इसमें कुछ मूल्यवान जानकारी शामिल है। –

+1

क्या कोई यह बता सकता है कि क्या यह चेतावनी प्रासंगिक है या नहीं? सेट में केवल असीसी वर्ण होते हैं और यदि 's1 [i]' एक विस्तृत चार है, तो डेल्फी win32 संकलक उस तुलना के लिए सही कोड उत्पन्न करता है। मैंने 's1: = 'Ł' की कोशिश की; अगर (एस 1 [1] ['ए'] में) तो ... ', क्योंकि' बाइट ('Ł') = 65 = बाइट ('ए') '। लेकिन इस तुलना के लिए संकलक सही कोड उत्पन्न करता है। – ventiseis

उत्तर

8

चेतावनी आपको बता रही है कि आपका कोड दोषपूर्ण हो सकता है। चूंकि सेट केवल 256 या उससे कम की सामान्यता वाले प्रकारों पर आधारित हो सकते हैं, आधार आकार को उस आकार में छोटा कर दिया जाता है। अब, CharWideChar के लिए उपनाम है और इसकी सामान्यता 65536 है। इसलिए चेतावनी आपको यह बताने के लिए है कि आपका प्रोग्राम आपकी अपेक्षा के अनुसार व्यवहार नहीं कर सकता है। उदाहरण के लिए, एक पूछ सकते हैं कि क्या यह अभिव्यक्ति का मूल्यांकन:

['A', chr(256)] = ['A'] 

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

अब ऐसा होता है कि आपका सेट, जो ['A'..'Z'] के रूप में अधिक संक्षेप में लिखा जा सकता है और लिखा जाना चाहिए, पूरी तरह से ASCII वर्णों से बना है। और ऐसा होता है (टिप्पणियों एंड्रियास और वेंटिज़िस के लिए धन्यवाद) कि उस मामले में संकलक in ऑपरेटर के बाईं ओर वर्ण के सामान्य मूल्य के बावजूद, इस तरह के सेट के लिए सही कोड उत्पन्न करता है। तो

if s1[i] in ['A'..'Z'] then 

चेतावनी के बावजूद सही कोड होगा। और संकलक यह पता लगाने में सक्षम है कि सेट के तत्व संगत हैं और कुशल कोड उत्पन्न करते हैं।

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

चेतावनी हालांकि परेशान है, और क्या आप वास्तव में इस चेतावनी को सुरक्षित रूप से अनदेखा कर सकते हैं जब के विशिष्ट विवरण याद रखने पर भरोसा करना चाहते हैं।एक inlined समारोह में

if (c >= 'A') and (c <= 'Z') then 
    .... 

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

function IsUpperCaseEnglishLetter(c: Char): Boolean; inline; 
begin 
    Result := (c >= 'A') and (c <= 'Z'); 
end; 

आपको यह भी पूछना चाहिए कि यह कोड एक प्रदर्शन बाधा है या नहीं। आपको इस तरह के एक कृत्रिम कार्यक्रम की बजाय अपने असली कार्यक्रम का समय चाहिए। मैं शर्त लगाऊंगा कि यह कोड एक बाधा नहीं है और यदि ऐसा है तो आपको मुख्य चालक के रूप में प्रदर्शन का इलाज नहीं करना चाहिए।

+0

सही है, एक बाधा नहीं है, लेकिन अगर यह निष्पादन समय को दोगुना करता है, तो यह हो सकता है। एफवाईआई, मैंने परीक्षण किया और आपके असमानता ऑपरेटरों के साथ प्रदर्शन में अंतर न्यूनतम है, 2384 -> 2355, 9 75 -> 9 5 9 एमएस। –

+1

लेकिन, आपका समाधान W1050 समस्या हल करता है, इतना अच्छा! :) –

+1

भले ही यह निष्पादन समय को दोगुना करता है, यह एक बाधा होने की संभावना नहीं है। आपका प्रोग्राम इस से अधिक करता है मुझे यकीन है। –

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