स्ट्रिंगबिल्डर के रूप में कुशल है

मान लीजिए मेरे पास सी # में एक स्ट्रिंगबिल्डर है जो यह करता है:

StringBuilder sb = new StringBuilder();
string cat = "cat";
sb.Append("the ").Append(cat).(" in the hat");
string s = sb.ToString();

यह उतना ही कुशल या अधिक कुशल होगा जितना:

string cat = "cat";
string s = String.Format("The {0} in the hat", cat);

यदि हां, तो क्यों?

EDIT

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

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

गलतफहमी के लिए खेद है

0
ro fr bn
कृपया भविष्य में सुधार की अनुमति देने के लिए इन्हें खोलें।
जोड़ा लेखक Mark Biek, स्रोत
एक विशेष मामले परिदृश्य में, इनमें से सबसे तेज़ नहीं है: यदि भाग को प्रतिस्थापित किया जाए तो आकार के बराबर बराबर है, तो आप स्ट्रिंग को जगह में बदल सकते हैं। दुर्भाग्य से, इसके लिए प्रतिबिंब या असुरक्षित कोड की आवश्यकता होती है और जानबूझकर स्ट्रिंग की अपरिवर्तनीयता का उल्लंघन करती है। एक अच्छा अभ्यास नहीं है, लेकिन अगर गति एक मुद्दा है ... :)
जोड़ा लेखक Abel, स्रोत
ऊपर दिए गए उदाहरण में string s = "टोपी में" + cat + ""; सबसे तेज़ हो सकता है जब तक कि इसे लूप में उपयोग नहीं किया जाता है, इस मामले में सबसे तेज़ स्ट्रिंगबिल्डर के साथ होगा लूप के बाहर शुरू किया गया।
जोड़ा लेखक Surya Pratap, स्रोत

12 उत्तर

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

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

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

0
जोड़ा
हाँ! String.Format का उपयोग करें जब ऐसा करने में कोई अर्थ हो, यानी जब आप तारों को स्वरूपित कर रहे हों। जब आप मैकेनिकल कॉन्सटेनेशन कर रहे हों तो स्ट्रिंग कॉन्सटेनेशन या स्ट्रिंगबिल्डर का उपयोग करें। हमेशा उस विधि को चुनने का प्रयास करें जो आपके इरादे को अगले रखरखाव के लिए संचारित करता है।
जोड़ा लेखक Rob, स्रोत

मैं सुझाव नहीं दूंगा, क्योंकि स्ट्रिंग.फॉर्मेट को संयोज के लिए डिज़ाइन नहीं किया गया था, यह एक तारीख जैसे विभिन्न इनपुट के आउटपुट को स्वरूपित करने के लिए डिज़ाइन किया गया था।

String s = String.Format("Today is {0:dd-MMM-yyyy}.", DateTime.Today);
0
जोड़ा

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

इस मामले में, मैं स्ट्रिंग का सुझाव दूंगा। फोर्मेट सबसे तेज़ है क्योंकि यह उस सटीक उद्देश्य के लिए डिज़ाइन है।

0
जोड़ा

मैं String.Format धीमे होने की अपेक्षा करता हूं - इसे स्ट्रिंग को पार्स करना होगा और फिर इसे संयोजित करना होगा।

नोट्स का जोड़ा:

  • Format is the way to go for user-visible strings in professional applications; this avoids localization bugs
  • If you know the length of the resultant string beforehand, use the StringBuilder(Int32) constructor to predefine the capacity
0
जोड़ा

मैंने कुछ त्वरित प्रदर्शन बेंचमार्क चलाए, और 10,000 से अधिक औसत 100,000 ऑपरेशन के लिए, पहली विधि (स्ट्रिंग बिल्डर) दूसरे (स्ट्रिंग प्रारूप) के लगभग आधा समय लेती है।

तो, अगर यह कम है, इससे कोई फर्क नहीं पड़ता। लेकिन अगर यह एक आम ऑपरेशन है, तो आप पहली विधि का उपयोग करना चाह सकते हैं।

0
जोड़ा

ओह भी, सबसे तेज़ होगा:

string cat = "cat";
string s = "The " + cat + " in the hat";
0
जोड़ा
@ वैभव सही है: इस मामले में, समापन सबसे तेज़ है। बेशक, अंतर तब तक महत्वहीन नहीं होगा जब तक कि कई बार बार-बार दोहराया न जाए, या शायद अधिक, अधिक बड़ी स्ट्रिंग पर संचालित हो।
जोड़ा लेखक Ben Collins, स्रोत
शायद टाइप करने के लिए सबसे तेज़;)
जोड़ा लेखक UpTheCreek, स्रोत
नहीं, स्ट्रिंग कॉन्सटेनेशन बेहद धीमा है, क्योंकि .NET इस स्ट्रिंग ऑपरेशंस के बीच आपके स्ट्रिंग चर के अतिरिक्त प्रतियां बनाता है, इस मामले में: दो अतिरिक्त प्रतियां और असाइनमेंट के लिए अंतिम प्रति। परिणाम: स्ट्रिंगबिल्डर की तुलना में बेहद खराब प्रदर्शन जो इस प्रकार के कोडिंग को पहले स्थान पर अनुकूलित करने के लिए बनाया गया है।
जोड़ा लेखक Abel, स्रोत
@Abel: उत्तर में विवरण की कमी हो सकती है, लेकिन इस विशेष उदाहरण में यह दृष्टिकोण सबसे तेज़ विकल्प है। कंपाइलर इसे एक स्ट्रिंग में परिवर्तित कर देगा। कॉनकैट() कॉल, इसलिए स्ट्रिंगबिल्डर के साथ प्रतिस्थापित करने से वास्तव में कोड धीमा हो जाएगा।
जोड़ा लेखक Dan C., स्रोत

String.Format uses a StringBuilder internally:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }

    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}

उपर्युक्त कोड mscorlib से एक स्निपेट है, इसलिए प्रश्न "कोड <�कोड> स्ट्रिंगबिल्डर। ऐपेंड() StringBuilder.AppendFormat() " से तेज़ हो जाता है?

बेंचमार्किंग के बिना मैं शायद कहूंगा कि उपरोक्त कोड नमूना .Append() का उपयोग करके अधिक तेज़ी से चलाएगा। लेकिन यह एक अनुमान है, उचित तुलना करने के लिए दोनों को बेंचमार्किंग और / या प्रोफाइलिंग करने का प्रयास करें।

इस चैप, जैरी डिक्सन ने कुछ बेंचमार्किंग की:

http://jdixon.dotnetdevelopersjournal.com/string_concatenation_stringbuilder_and_stringformat.htm

अपडेट किया गया:

अफसोस की बात है कि उपरोक्त लिंक की मृत्यु हो गई है। हालांकि वे बैक मशीन पर अभी भी एक प्रति है:

http: //web.archive। org / वेब / 20090417100252 / http: //jdixon.dotnetdevelopersjournal.com/string_concatenation_stringbuilder_and_stringformat.htm

दिन के अंत में यह निर्भर करता है कि आपकी स्ट्रिंग स्वरूपण को दोहराया जा रहा है या नहीं, यानी आप 100 से अधिक मेगाबाइट टेक्स्ट पर कुछ गंभीर टेक्स्ट प्रोसेसिंग कर रहे हैं, या फिर जब उपयोगकर्ता एक बटन पर क्लिक करता है तो उसे कॉल किया जा रहा है या नहीं। जब तक आप कुछ विशाल बैच प्रसंस्करण नौकरी नहीं कर रहे हैं, मैं स्ट्रिंग.फॉर्मैट के साथ रहूंगा, यह कोड पठनीयता की सहायता करता है। यदि आपको एक पर्फ की बाधा पर संदेह है तो अपने कोड पर एक प्रोफाइलर चिपकाएं और देखें कि यह वास्तव में कहां है।

0
जोड़ा
जैरी डिक्सन के पेज पर बेंचमार्क के साथ एक समस्या यह है कि वह कभी भी StringBuilder ऑब्जेक्ट पर .ToString() को कॉल नहीं करता है। बहुत सारे पुनरावृत्तियों में, उस समय एक बड़ा अंतर आता है, और इसका मतलब है कि वह सेब से सेब की तुलना नहीं कर रहा है। यही कारण है कि वह StringBuilder के लिए इस तरह के शानदार प्रदर्शन दिखाता है और शायद उसके आश्चर्य के लिए खाते हैं। मैंने बस उस गलती को सुधारने के लिए बेंचमार्क दोहराया और अपेक्षित परिणाम प्राप्त किए: स्ट्रिंग + ऑपरेटर सबसे तेज़ था, उसके बाद स्ट्रिंगबिल्डर , स्ट्
जोड़ा लेखक Ben Collins, स्रोत
6 साल बाद, यह अब इतना नहीं है। नेट 4 में, string.Format() स्ट्रिंगबिल्डर उदाहरण बनाता है और इसे कैश करता है, जिससे यह कुछ परीक्षण मामलों में स्ट्रिंगबिल्डर से तेज हो सकता है। मैंने नीचे दिए गए उत्तर में एक संशोधित बेंचमार्क लगाया है (जो अभी भी कहता है कि कॉन्सैट सबसे तेज़ है और मेरे टेस्ट केस के लिए, प्रारूप स्ट्रिंगबिल्डर से 10% धीमा है)।
जोड़ा लेखक Chris F Carroll, स्रोत

String.Format स्ट्रिंगबिल्डर आंतरिक रूप से उपयोग करता है ... इसलिए तार्किक रूप से यह विचार करता है कि यह अधिक ओवरहेड के कारण थोड़ा कम प्रदर्शनकारी होगा। हालांकि, एक साधारण स्ट्रिंग कॉन्सटेनेशन एक महत्वपूर्ण डिग्री से दो अन्य लोगों के बीच एक स्ट्रिंग इंजेक्शन करने का सबसे तेज़ तरीका है। यह साक्ष्य रिको मारियानी ने कई साल पहले अपने पहले प्रदर्शन क्विज़ में प्रदर्शित किया था। सरल तथ्य यह है कि concatenations ... जब स्ट्रिंग भागों की संख्या ज्ञात है (बिना सीमा के..तुम एक हजार भागों को जोड़ सकते हैं ... जब तक आप इसे हमेशा 1000 भागों जानते हैं) ... हमेशा स्ट्रिंगबिल्डर या स्ट्रिंग। फॉर्मेट। उन्हें एक स्मृति स्मृति आवंटन के साथ एक स्मृति स्मृति आवंटन के साथ किया जा सकता है। यहां सबूत है

और यहां कुछ स्ट्रिंग के लिए वास्तविक कोड है। कॉनकैट विधियों, जो अंत में फिलस्टिंग चेक किए जाते हैं जो पॉइंटर्स का उपयोग स्मृति की प्रतिलिपि बनाने के लिए करता है (परावर्तक के माध्यम से निकाला जाता है):

public static string Concat(params string[] values)
{
    int totalLength = 0;

    if (values == null)
    {
        throw new ArgumentNullException("values");
    }

    string[] strArray = new string[values.Length];

    for (int i = 0; i < values.Length; i++)
    {
        string str = values[i];
        strArray[i] = (str == null) ? Empty : str;
        totalLength += strArray[i].Length;

        if (totalLength < 0)
        {
            throw new OutOfMemoryException();
        }
    }

    return ConcatArray(strArray, totalLength);
}

public static string Concat(string str0, string str1, string str2, string str3)
{
    if (((str0 == null) && (str1 == null)) && ((str2 == null) && (str3 == null)))
    {
        return Empty;
    }

    if (str0 == null)
    {
        str0 = Empty;
    }

    if (str1 == null)
    {
        str1 = Empty;
    }

    if (str2 == null)
    {
        str2 = Empty;
    }

    if (str3 == null)
    {
        str3 = Empty;
    }

    int length = ((str0.Length + str1.Length) + str2.Length) + str3.Length;
    string dest = FastAllocateString(length);
    FillStringChecked(dest, 0, str0);
    FillStringChecked(dest, str0.Length, str1);
    FillStringChecked(dest, str0.Length + str1.Length, str2);
    FillStringChecked(dest, (str0.Length + str1.Length) + str2.Length, str3);
    return dest;
}

private static string ConcatArray(string[] values, int totalLength)
{
    string dest = FastAllocateString(totalLength);
    int destPos = 0;

    for (int i = 0; i < values.Length; i++)
    {
        FillStringChecked(dest, destPos, values[i]);
        destPos += values[i].Length;
    }

    return dest;
}

private static unsafe void FillStringChecked(string dest, int destPos, string src)
{
    int length = src.Length;

    if (length > (dest.Length - destPos))
    {
        throw new IndexOutOfRangeException();
    }

    fixed (char* chRef = &dest.m_firstChar)
    {
        fixed (char* chRef2 = &src.m_firstChar)
        {
            wstrcpy(chRef + destPos, chRef2, length);
        }
    }
}

तो फिर:

string what = "cat";
string inthehat = "The " + what + " in the hat!";

का आनंद लें!

0
जोड़ा
नेट 4 में, string.Format कैश और एक स्ट्रिंगबिल्डर उदाहरण का पुन: उपयोग करता है ताकि कुछ उपयोगों में तेजी से हो।
जोड़ा लेखक Chris F Carroll, स्रोत

यह वास्तव में निर्भर करता है। कुछ concatenations के साथ छोटे तारों के लिए, यह तारों को जोड़ने के लिए वास्तव में तेजी से है।

String s = "String A" + "String B";

लेकिन बड़ी स्ट्रिंग (बहुत बड़े तार) के लिए, यह स्ट्रिंगबिल्डर का उपयोग करने के लिए और अधिक कुशल है।

0
जोड़ा

MSDN दस्तावेज़ से:

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

0
जोड़ा

अगर केवल स्ट्रिंग के कारण। फोर्मेट वास्तव में ऐसा नहीं करता जो आप सोच सकते हैं, यहां 6 साल बाद नेट 45 पर परीक्षणों का पुनर्मिलन किया गया है।

Concat अभी भी सबसे तेज़ है लेकिन वास्तव में यह 30% से कम अंतर है। स्ट्रिंगबिल्डर और प्रारूप मुश्किल से 5-10% से भिन्न है। मुझे कुछ बार परीक्षण चलाने में 20% की विविधताएं मिलीं।

Milliseconds, एक लाख पुनरावृत्तियों:

  • Concatenation: 367
  • प्रत्येक कुंजी के लिए नया स्ट्रिंगबिल्डर: 452
  • कैश स्ट्रिंगबिल्डर: 41 9
  • string.Format: 475

जो पाठ मैं लेता हूं वह यह है कि प्रदर्शन अंतर छोटा होता है और इसलिए आपको सबसे सरल पठनीय कोड लिखना बंद नहीं करना चाहिए। जो मेरे पैसे के लिए अक्सर होता है लेकिन हमेशा a + b + c नहीं होता है।

const int iterations=1000000;
var keyprefix= this.GetType().FullName;
var maxkeylength=keyprefix + 1 + 1+ Math.Log10(iterations);
Console.WriteLine("KeyPrefix \"{0}\", Max Key Length {1}",keyprefix, maxkeylength);

var concatkeys= new string[iterations];
var stringbuilderkeys= new string[iterations];
var cachedsbkeys= new string[iterations];
var formatkeys= new string[iterations];

var stopwatch= new System.Diagnostics.Stopwatch();
Console.WriteLine("Concatenation:");
stopwatch.Start();

for(int i=0; ix[1]=='-');
Console.WriteLine(referToTheComputedValuesSoCompilerCantOptimiseTheLoopsAway);
0
जोड़ा
"String.Format ठीक से नहीं करता जो आप सोच सकते हैं" मेरा मतलब है कि 4.5 स्रोत कोड में यह एक कैश किए गए स्ट्रिंगबिल्डर उदाहरण को बनाने और पुन: उपयोग करने का प्रयास करता है। तो मैंने परीक्षण में उस दृष्टिकोण को शामिल किया
जोड़ा लेखक Chris F Carroll, स्रोत

It really depends on your usage pattern.
A detailed benchmark between string.Join, string,Concat and string.Format can be found here: String.Format Isn't Suitable for Intensive Logging

0
जोड़ा