Vra

As ek 'n StringBuilder in C # wat dit doen:

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

sou dit wees as doeltreffende of meer doeltreffend as om:

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

As dit so is, hoekom?

wysig

Na 'n paar interessante antwoorde, het ek besef ek waarskynlik 'n bietjie duideliker moes gewees het in wat ek vra. Ek is nie soseer vra waarvoor was vinniger by concatenating n string, maar wat is vinniger by spuit 'n string na 'n ander.

In beide gevalle hierbo ek wil een of meer snare te spuit in die middel van 'n vooraf gedefinieerde sjabloon string.

Jammer vir die verwarring

Was dit nuttig?

Oplossing

Nota: Hierdie vraag is geskryf toe NET 2.0 was die huidige weergawe. Dit kan nie meer van toepassing op latere weergawes.

String.Format gebruik 'n StringBuilder intern:

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();
}

Die bogenoemde kode is 'n uittreksel uit mscorlib, so die vraag word "is vinniger as StringBuilder.Append() StringBuilder.AppendFormat()"?

Sonder benchmarking Ek sal waarskynlik sê dat die kode monster bo vinniger sal hardloop met behulp van .Append(). Maar dit is 'n raaiskoot, probeer benchmarking en / of profilering die twee aan 'n behoorlike vergelyking kry.

Dit kêrel, Jerry Dixon, het 'n paar benchmarking:

  

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

Opdateer:

Ongelukkig is die skakel hierbo het sedertdien gesterf. Maar daar is nog 'n kopie op die pad terug masjien:

  

http: //web.archive org / web / 20090417100252 / http: //jdixon.dotnetdevelopersjournal.com/string_concatenation_stringbuilder_and_stringformat.htm

Aan die einde van die dag is dit hang af of jou string opmaak gaan herhaaldelik genoem word, dit wil sê jy doen 'n paar ernstige teks verwerking meer as 100 se van MG teks, en of dit word genoem as 'n gebruiker 'n knoppie nou druk en weer. Tensy jy besig met 'n groot bondel verwerking werk Ek sal vashou aan String.Format, dit help kode leesbaarheid. As jy 'n perf bottelnek vermoed dan hou 'n profiler op jou kode en sien waar dit werklik is.

Ander wenke

Van die MSDN dokumentasie :

  

Die vertoning van 'n aaneenskakellling operasie vir 'n String of StringBuilder voorwerp hang af van hoe dikwels 'n geheue toekenning plaasvind. 'N string aaneenskakellling werking ken altyd geheue, terwyl 'n StringBuilder aaneenskakellling operasie net ken geheue as die StringBuilder voorwerp buffer is te klein om die nuwe data te akkommodeer. Gevolglik is die String klas is verkieslik vir 'n aaneenskakellling operasie as 'n vaste aantal String voorwerpe is aaneen. In daardie geval, kan die individu aaneenskakellling bedrywighede selfs gekombineer in 'n enkele operasie deur die samesteller. A StringBuilder voorwerp is verkieslik vir 'n aaneenskakellling operasie as 'n arbitrêre aantal snare is saamgevoeg; Byvoorbeeld, as 'n lus Heg 'n ewekansige getal snare van die gebruiker se toevoer.

Ek het 'n paar vinnige prestasie maatstawwe, en vir 100,000 bedrywighede gemiddeld meer as 10 lopies, die eerste metode (String Bouwer) neem byna die helfte van die tyd van die tweede (String Format).

Dus, as dit is ongereelde, dit maak nie saak. Maar as dit is 'n algemene werking, dan kan jy die eerste metode te gebruik.

Ek sou verwag String.Format om stadiger wees -. Dit moet die string te ontleed en dan koppel dit

Egpaar van notas:

  • Format is die pad om te gaan vir die gebruiker-sigbare snare in professionele programme; hierdie vermy lokalisering foute
  • As jy die lengte van die gevolglike string weet vooraf, gebruik die StringBuilder (int32) constructor om die kapasiteit definieer

As net omdat string.Format nie presies doen wat jy dink, hier is 'n tik van die toetse 6 jaar later op Net45.

Concat is nog vinnigste maar regtig dit is minder as 30% verskil. StringBuilder en formaat verskil deur skaars 5-10%. Ek het variasies van 20% loop die toetse 'n paar keer.

Millisekondes, 'n miljoen iterasies:

  • Aaneenhegging: 367
  • New StringBuilder vir elke sleutel: 452
  • Cached StringBuilder: 419
  • string.Format: 475

Die les wat ek weg te neem is dat die prestasie verskil is onbeduidend en so moet dit nie stop jy skryf die eenvoudigste leesbare kode wat jy kan. Wat vir my geld is dikwels maar nie altyd 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; i<iterations; i++){
    var key1= keyprefix+":" + i.ToString();
    concatkeys[i]=key1;
}

Console.WriteLine(stopwatch.ElapsedMilliseconds);

Console.WriteLine("New stringBuilder for each key:");
stopwatch.Restart();

for(int i=0; i<iterations; i++){
    var key2= new StringBuilder(keyprefix).Append(":").Append(i.ToString()).ToString();
    stringbuilderkeys[i]= key2;
}

Console.WriteLine(stopwatch.ElapsedMilliseconds);

Console.WriteLine("Cached StringBuilder:");
var cachedSB= new StringBuilder(maxkeylength);
stopwatch.Restart();

for(int i=0; i<iterations; i++){
    var key2b= cachedSB.Clear().Append(keyprefix).Append(":").Append(i.ToString()).ToString();
    cachedsbkeys[i]= key2b;
}

Console.WriteLine(stopwatch.ElapsedMilliseconds);

Console.WriteLine("string.Format");
stopwatch.Restart();

for(int i=0; i<iterations; i++){
    var key3= string.Format("{0}:{1}", keyprefix,i.ToString());
    formatkeys[i]= key3;
}

Console.WriteLine(stopwatch.ElapsedMilliseconds);

var referToTheComputedValuesSoCompilerCantOptimiseTheLoopsAway= concatkeys.Union(stringbuilderkeys).Union(cachedsbkeys).Union(formatkeys).LastOrDefault(x=>x[1]=='-');
Console.WriteLine(referToTheComputedValuesSoCompilerCantOptimiseTheLoopsAway);

Ek dink in die meeste gevalle soos hierdie duidelikheid, en nie doeltreffendheid, moet jou grootste bekommernis wees. Tensy jy saam ton van snare is vergruis, of iets te bou vir 'n laer-aangedrewe mobiele toestel, hierdie sal waarskynlik nie veel van 'n duik te maak in jou hardloop spoed.

Ek het gevind dat, StringBuilder in gevalle waar ek snare bou in 'n redelik lineêre mode, óf doen reguit concatenations of die gebruik van jou beste opsie. Ek stel voor dat dit in gevalle waar die meerderheid van die string wat jy bou is dinamies. Sedert baie min van die teks is staties, die belangrikste ding is dat dit duidelik waar elke stukkie van dinamiese teks is in geval dit behoeftes opgedateer in die toekoms geplaas.

Aan die ander kant, as jy praat oor 'n groot deel van statiese teks met twee of drie veranderlikes in dit, selfs al is dit 'n bietjie minder doeltreffend, ek dink die duidelikheid jy baat by string.Format maak dit die moeite werd . Ek gebruik hierdie vroeër vandeesweek toe om te 'n bietjie van 'n dinamiese teks plaas in die middel van 'n 4 bladsy-dokument. Dit sal makliker wees om daardie groot stuk van die teks te werk as sy in een stuk as om drie stukke wat jy saam koppel werk.

String.Format gebruik StringBuilder intern ... so logies wat lei tot die idee dat dit 'n bietjie minder performante sou wees as gevolg van meer oorhoofse. Maar 'n eenvoudige string aaneenskakellling is die vinnigste metode van die spuit van een string tussen twee ander ... deur 'n beduidende mate. Hierdie bewyse is gedemonstreer deur Rico Mariani in sy heel eerste Performance Quiz, jare gelede. Eenvoudige feit is dat concatenations ... wanneer die aantal string dele bekend is (sonder limitation..you kon koppel 'n duisend dele ... so lank as wat jy weet sy altyd 1000 dele) ... is altyd vinniger as StringBuilder of String .Format. Hulle kan uitgevoer word met 'n enkele toekenning geheue 'n 'n reeks van geheue kopieë. Hier is die bewys

En hier is die werklike kode vir 'n paar String.Concat metodes, wat uiteindelik FillStringChecked noem wat wysers gebruik om geheue (onttrek via Reflector) kopieer:

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);
        }
    }
}

So dan:

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

Geniet dit!

O ook, die vinnigste sou wees:

string cat = "cat";
string s = "The " + cat + " in the hat";

Dit hang regtig. Vir klein snare met 'n paar concatenations, dit is eintlik vinniger net om die snare voeg.

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

Maar vir 'n groter string (baie baie groot snare), is dit dan meer doeltreffend te StringBuilder gebruik.

  

In beide gevalle hierbo ek wil een of meer snare te spuit in die middel van 'n vooraf gedefinieerde sjabloon string.

In welke geval, sou ek raai String.Format is die vinnigste, want dit is ontwerp vir daardie presiese doel.

Dit hang af van jou gebruik patroon.
'N Gedetailleerde maatstaf tussen string.Join, string,Concat en string.Format kan hier gevind word: String.Format is nie geskik vir Intensiewe Logging

Ek stel voor nie, aangesien String.Format nie ontwerp is vir aaneenskakellling, dit was ontwerp vir formatering die produksie van verskeie insette soos 'n datum.

String s = String.Format("Today is {0:dd-MMM-yyyy}.", DateTime.Today);
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top