StringBuilder. Добавьте по сравнению с StringBuilder. AppendFormat

, так что это представляется возможным при использовании Extract :

function getShape(type: T): Extract {}

36
задан Samuel 2 April 2009 в 17:03
поделиться

9 ответов

Невозможно сказать, не зная размера string1 и string2.

С вызовом к AppendFormat, это предварительно выделит буфер только когда-то, учитывая длину строки формата и строк, которые будут вставлены и затем свяжут все и вставлять его в буфер. Для очень больших строк это будет выгодно по отдельным вызовам для Append который мог бы заставить буфер расширяться многократно.

Однако три вызова к Append мог бы или не мог бы инициировать рост буфера, и та проверка выполнена каждый вызов. Если строки будут достаточно маленькими, и никакое буферное расширение не инициировано, то это будет быстрее, чем вызов к AppendFormat потому что это не должно будет анализировать строку формата для выяснения, где сделать замены.

Больше данных необходимо для категорического ответа

Нужно отметить, что существует мало обсуждения использования помех Concat метод на String класс (использование ответа Jon AppendWithCapacity напомненный меня об этом). Его результаты испытаний показывают, что, чтобы быть лучшим случаем (принимающий Вас не должны использовать в своих интересах определенный спецификатор формата). String.Concat делает то же самое, в котором это предопределит длину строк, чтобы связать и предварительно выделить буфер (с немного больше служебным из-за конструкций цикличного выполнения через параметры). Это - производительность, будет сопоставимым с Jon AppendWithCapacity метод.

Или, просто простой оператор сложения, так как это компилирует в вызов к String.Concat так или иначе, с протестом, что все дополнения находятся в том же выражении:

// One call to String.Concat.
string result = a + b + c;

НЕТ

// Two calls to String.Concat.
string result = a + b;
result = result + c;

Для всех те, которые поднимают тестовый код

Необходимо выполнить тестовые сценарии в отдельных выполнениях (или по крайней мере, выполнить GC между измерением отдельных тестовых прогонов). Причина этого - это, если Вы действительно говорите, 1 000 000 выполнений, создавая новое StringBuilder в каждом повторении цикла для одного теста, и затем Вы запускаете следующий тест, который циклично выполняет то же количество раз, создавая еще 1 000 000 StringBuilder экземпляры, GC больше, чем, вероятно, вступит во время второго теста и препятствует своей синхронизации.

41
ответ дан Community 27 November 2019 в 05:33
поделиться

casperOne корректен. После того как Вы достигаете определенного порога, Append() метод становится медленнее, чем AppendFormat(). Здесь различные длины и протекли галочки 100 000 повторений каждого метода:

Длина: 1

Append()       - 50900
AppendFormat() - 126826

Длина: 1000

Append()       - 1241938
AppendFormat() - 1337396

Длина: 10,000

Append()       - 12482051
AppendFormat() - 12740862

Длина: 20,000

Append()       - 61029875
AppendFormat() - 60483914

Когда строки с длиной около 20,000 представлены, AppendFormat() функция немного превзойдет по характеристикам Append().

Почему это происходит? См. ответ casperOne.

Править:

Я повторно выполнил каждый тест индивидуально в соответствии с конфигурацией Выпуска и обновил результаты.

22
ответ дан Community 27 November 2019 в 05:33
поделиться

casperOne совершенно точен, что он зависит от данных. Однако предположите запись этого как библиотеки классов для третьих сторон для потребления - который Вы использовали бы?

Одна опция состояла бы в том, чтобы добраться, лучший из обоих миров - удаются, сколько данных Вы на самом деле оказываетесь перед необходимостью добавлять и затем использовать StringBuilder. EnsureCapacity для проверки нам только нужен единственный буфер, изменяют размер.

Если бы я был не слишком побеспокоен, хотя, я использовал бы Append x3 - это кажется "более вероятным", чтобы быстрее, как проанализировать маркеры формата строки на каждом вызове, ясно делать-работа.

Обратите внимание, что я попросил у команды BCL своего рода "кэшируемого средства форматирования", которое мы могли создать использование строки формата и затем повторного использования неоднократно. Является сумасшедшим, что платформа должна проанализировать строку формата каждый раз, когда это используется.

Править: Хорошо, я отредактировал код John's несколько для гибкости и добавил "AppendWithCapacity", который просто разрабатывает необходимую способность сначала. Вот результаты для различных длин - для длины 1 я использовал 1 000 000 повторений; для всех других длин я использовал 100,000. (Это должно было только получить разумное время выполнения.) Все случаи находятся в millis.

К сожалению, таблицы действительно не работают в ТАК. Длины равнялись 1, 1000, 10000, 20000

Времена:

  • Добавьте: 162, 475, 7997, 17970
  • AppendFormat: 392, 499, 8541, 18993
  • AppendWithCapacity: 139, 189, 1558, 3085

Таким образом, как это произошло, я никогда не видел, что удар AppendFormat Добавил - но я действительно видел победу AppendWithCapacity очень высокой маржей.

Вот полный код:

using System;
using System.Diagnostics;
using System.Text;

public class StringBuilderTest
{            
    static void Append(string string1, string string2)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(string1);
        sb.Append("----");
        sb.Append(string2);
    }

    static void AppendWithCapacity(string string1, string string2)
    {
        int capacity = string1.Length + string2.Length + 4;
        StringBuilder sb = new StringBuilder(capacity);
        sb.Append(string1);
        sb.Append("----");
        sb.Append(string2);
    }

    static void AppendFormat(string string1, string string2)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("{0}----{1}", string1, string2);
    }

    static void Main(string[] args)
    {
        int size = int.Parse(args[0]);
        int iterations = int.Parse(args[1]);
        string method = args[2];

        Action<string,string> action;
        switch (method)
        {
            case "Append": action = Append; break;
            case "AppendWithCapacity": action = AppendWithCapacity; break;
            case "AppendFormat": action = AppendFormat; break;
            default: throw new ArgumentException();
        }

        string string1 = new string('x', size);
        string string2 = new string('y', size);

        // Make sure it's JITted
        action(string1, string2);
        GC.Collect();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < iterations; i++)
        {
            action(string1, string2);
        }
        sw.Stop();
        Console.WriteLine("Time: {0}ms", (int) sw.ElapsedMilliseconds);
    }
}
12
ответ дан Community 27 November 2019 в 05:33
поделиться

Append будет быстрее в большинстве случаев, потому что существует много перегрузок к тому методу, которые позволяют компилятору называть корректный метод. Так как Вы используете Strings StringBuilder может использовать String перегрузка для Append.

AppendFormat берет a String и затем Object[] что означает, что формат должен будет быть проанализирован и каждый Object в массиве должен будет быть ToString'd прежде чем это сможет быть добавлено к StringBuilder's внутренний массив.

Примечание: К точке casperOne - трудно дать точный ответ без большего количества данных.

6
ответ дан Andrew Hare 27 November 2019 в 05:33
поделиться

StringBuilder также расположился каскадом, добавляет: Append() возвраты StringBuilder самостоятельно, таким образом, можно написать код как это:

StringBuilder sb = new StringBuilder();
sb.Append(string1)
  .Append("----")
  .Append(string2);

Чистый, и это генерирует меньше IL-кода (хотя это - действительно микрооптимизация).

2
ответ дан casperOne 27 November 2019 в 05:33
поделиться

Конечно, профиль для знания наверняка в каждом случае.

Тем не менее я думаю в целом, что это будет первый, потому что Вы неоднократно не анализируете строку формата.

Однако разница была бы очень небольшой. До такой степени, что действительно необходимо рассмотреть использование AppendFormat в большинстве случаев так или иначе.

1
ответ дан casperOne 27 November 2019 в 05:33
поделиться

Я предположил бы, что это был вызов, который сделал наименьшее количество объема работы. Добавьте просто связывает строки, где AppendFormat делает строковые замены. Конечно, в эти дни Вы никогда не можете говорить...

0
ответ дан Paul W Homer 27 November 2019 в 05:33
поделиться

1 должен быть более быстрый becuase, он просто добавляет строки, тогда как 2 должен создать строку на основе формата и затем добавить строку. Таким образом, существует дополнительный шаг там.

0
ответ дан Micah 27 November 2019 в 05:33
поделиться

Быстрее 1 в Вашем случае однако, это не справедливое сравнение. Необходимо спросить StringBuilder.AppendFormat() по сравнению с StringBuilder.Append(string.Format()) - где первый происходит быстрее из-за внутренней работы с массивом символов.

Ваша вторая опция более читаема все же.

0
ответ дан Yousha Aleayoub 27 November 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: