Попробуйте этот код.
Это слегка измененная версия вашего кода.
1. Я удалил Console.WriteLine, поскольку он, вероятно, на несколько порядков медленнее, чем то, что я пытаюсь измерить.
2. Я запускаю секундомер перед циклом и останавливаю его сразу после этого, таким образом, я не теряю точности, если для выполнения функции требуется, например, 26,4 такта.
3. То, как вы разделили результат на несколько итераций, было неверным. Посмотрите, что произойдет, если у вас есть 1000 миллисекунд и 100 миллисекунд. В обеих ситуациях вы получите 0 мс после деления на 1000000.
Stopwatch s = new Stopwatch();
var p = new { FirstName = "Bill", LastName = "Gates" };
int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;
string result;
s.Start();
for (var i = 0; i < n; i++)
result = (p.FirstName + " " + p.LastName);
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();
s.Start();
for (var i = 0; i < n; i++)
result = string.Format("{0} {1}", p.FirstName, p.LastName);
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();
Console.Clear();
Console.WriteLine(n.ToString()+" x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Thread.Sleep(4000);
Это мои результаты:
1000000 x result = string.Format ("{0} {1}", p.FirstName, p.LastName); потребовалось: 618мс - 2213706 тиков
1000000 x результат = (p.FirstName + "" + p.LastName); заняло: 166мс - 595610 тиков
Michał Piaskowski
источник
string.Format
, который не использует какие-либо составные функции форматирования (то есть просто простые{0}
) и заменить их значительно более быстрой конкатенацией строк. Интересно, что такой подвиг достижим с существующим переписчиком IL, таким как PostSharp.Я поражен, что так много людей сразу хотят найти код, который выполняется быстрее всего. Если ОДИН МИЛЛИОН итераций ИСПОЛЬЗУЕТСЯ менее секунды, обрабатывается ли это ЛЮБОМ СПОСОБОМ, заметным для конечного пользователя? Не очень вероятно.
Я бы пошел с
String.Format
вариант, только потому, что он имеет больше смысла с архитектурной точки зрения. Я не забочусь о производительности, пока она не станет проблемой (и если бы это случилось, я бы спросила себя: нужно ли мне объединять миллион имен одновременно? Конечно, они не все уместятся на экране ...)Подумайте, хочет ли ваш клиент позже изменить его, чтобы он мог настроить, отображать
"Firstname Lastname"
или"Lastname, Firstname."
с опцией «Формат», это легко - просто поменяйте строку формата. С concat вам понадобится дополнительный код. Конечно, в этом конкретном примере это не имеет большого значения, но нужно экстраполировать.источник
О, дорогой - после прочтения одного из других ответов я попытался изменить порядок операций, поэтому сначала выполняю конкатенацию, а затем String.Format ...
Таким образом, порядок операций имеет ОГРОМНОЕ различие, или, скорее, самая первая операция ВСЕГДА намного медленнее.
Вот результаты прогона, в котором операции выполняются более одного раза. Я пытался изменить порядок, но, как правило, все по тем же правилам, как только первый результат игнорируется:
Как вы можете видеть, последующие прогоны того же метода (я преобразовал код в 3 метода) постепенно ускоряются. Наиболее быстрым представляется метод Console.WriteLine (String.Concat (...)), за которым следует обычная конкатенация и затем отформатированные операции.
Первоначальная задержка при запуске, вероятно, является инициализацией Console Stream, так как установка Console.Writeline («Start!») До того, как первая операция вернет все строки в соответствие.
источник
Строки являются неизменяемыми, это означает, что один и тот же крошечный фрагмент памяти используется снова и снова в вашем коде. Добавление тех же двух строк вместе и создание одной и той же новой строки снова и снова не влияет на память. .Net достаточно умен, чтобы использовать ту же ссылку на память. Поэтому ваш код не проверяет разницу между двумя методами concat.
Попробуйте это для размера:
Пример вывода:
источник
string.Format
стоит крошечной производительности здесь. Архитектурно это лучше, поскольку это означает, что вы можете изменить формат более легко. Но струнный строитель я действительно не вижу смысла. Любой другой поток здесь говорит, что вы должны использовать Stringbuilder вместо объединения строк. В чем преимущество? Очевидно, не скорость, как доказывает этот тест.Жаль бедных переводчиков
Если ты знаешь ваше приложение останется на английском языке, тогда хорошо, сохраните отметки времени. Тем не менее, многие культуры обычно видят Фамилию Имя, например, в адресах.
Так что пользуйтесь
string.Format()
, особенно если вы когда-нибудь отправите свое приложение куда-нибудь, где английский не является родным языком.источник
string.Format()
вести себя по-разному в разных культурах? Не будет ли по-прежнему печататься имя, затем фамилия? Похоже, что вам придется принимать во внимание различную культуру в обеих ситуациях. Я чувствую, что здесь что-то упущено.string.Format()
знать, что вы используете имя для адреса? Еслиstring.Format()
поменять местами{0} {1}
на основе культуры, я бы посчитал это сломанным.Вот мои результаты за 100 000 итераций:
И вот код стенда:
Итак, я не знаю, чей ответ пометить как ответ :)
источник
Конкатенация строк хороша в таком простом сценарии - она сложнее с чем-либо более сложным, чем даже LastName, FirstName. С форматом, который вы можете сразу увидеть, какой будет конечная структура строки при чтении кода, с конкатенацией становится практически невозможно сразу увидеть конечный результат (за исключением очень простого примера, подобного этому).
В конечном итоге это означает, что когда вы вернетесь, чтобы внести изменения в формат строки, у вас будет возможность всплыть и внести некоторые изменения в строку формата, или поморщить бровь и начать перемещаться по всем виды средств доступа к свойствам, смешанные с текстом, что, скорее всего, создает проблемы.
Если вы используете .NET 3.5, вы можете использовать метод расширения, подобный этому, и получить легкий переход от синтаксиса манжеты, например:
Наконец, по мере усложнения вашего приложения вы можете решить, что для разумного сохранения строк в вашем приложении вы хотите переместить их в файл ресурсов для локализации или просто в статический помощник. Это будет НАМНОГО легче достичь, если вы постоянно используете форматы, и ваш код может быть просто реорганизован для использования чего-то вроде
источник
Для очень простых манипуляций я бы использовал конкатенацию, но как только вы выйдете за 2 или 3 элемента, формат становится более подходящим IMO.
Еще одна причина, по которой предпочтение отдается String.Format, заключается в том, что строки .NET являются неизменяемыми, и при таком способе создается меньше временных / промежуточных копий.
источник
Хотя я полностью понимаю предпочтения стиля и выбрал конкатенацию для своего первого ответа, частично основываясь на моих собственных предпочтениях, часть моего решения была основана на мысли, что конкатенация будет быстрее. Итак, из любопытства я проверил это, и результаты были ошеломляющими, особенно для такой маленькой нити.
Используя следующий код:
Я получил следующие результаты:
Использование метода форматирования более чем в 100 раз медленнее! Конкатенация даже не регистрировалась как 1 мс, поэтому я также выводил тики таймера.
источник
Начиная с C # 6.0, для этого можно использовать интерполированные строки , что еще больше упрощает формат.
Интерполированные строки имеют производительность, аналогичную String.Format, но улучшают читаемость и сокращают синтаксис из-за того, что значения и выражения вставляются в строку.
Пожалуйста, также обратитесь к этой статье dotnetperls по интерполяции строк.
Если вы ищете способ форматирования ваших строк по умолчанию, это имеет смысл с точки зрения читабельности и производительности (за исключением случаев, когда микросекунды будут иметь значение в вашем конкретном случае использования).
источник
Для базовой конкатенации строк я обычно использую второй стиль - легче читать и проще. Однако, если я делаю более сложную комбинацию строк, я обычно выбираю String.Format.
String.Format экономит много цитат и плюсов ...
Сохранено только несколько символов, но я думаю, что в этом примере формат делает его намного чище.
источник
Лучшим тестом было бы наблюдать за вашей памятью, используя Perfmon и счетчики памяти CLR. Насколько я понимаю, единственная причина, по которой вы хотите использовать String.Format вместо простой конкатенации строк, заключается в том, что поскольку строки являются неизменяемыми, вы без необходимости загружаете сборщик мусора временными строками, которые должны быть восстановлены в следующем проходе.
StringBuilder и String.Format, хотя и потенциально медленнее, но более эффективны в использовании памяти.
Что плохого в конкатенации строк?
источник
Обычно я предпочитаю первое, так как особенно, когда строки становятся длинными, их гораздо легче читать.
Другим преимуществом является, я полагаю, одно из показателей производительности, поскольку последний фактически выполняет 2 оператора создания строки перед передачей окончательной строки в метод Console.Write. Я полагаю, что String.Format использует StringBuilder под крышками, поэтому избегают множественных конкатенаций.
Однако следует отметить, что если параметры, которые вы передаете в String.Format (и другие такие методы, как Console.Write), являются типами значений, то перед передачей они будут помещены в коробку, что может привести к снижению производительности. Сообщение в блоге об этом здесь .
источник
Через неделю, 19 августа 2015 года, этому вопросу будет ровно семь (7) лет. Теперь есть лучший способ сделать это. Лучше с точки зрения удобства сопровождения, поскольку я не проводил никакого теста производительности по сравнению с простым конкатенацией строк (но имеет ли это значение в наши дни - разница в несколько миллисекунд?). Новый способ сделать это с C # 6.0 :
Эта новая функция лучше , IMO, и на самом деле лучше в нашем случае, поскольку у нас есть коды, в которых мы строим строки запросов, значения которых зависят от некоторых факторов. Представьте себе одну строку запроса, где у нас есть 6 аргументов. Так что вместо того, чтобы сделать, например:
в может быть написано так, и это легче читать:
источник
источник
Я выбираю на основе читабельности. Я предпочитаю вариант форматирования, когда вокруг переменных есть текст. В этом примере:
Вы понимаете значение даже без имен переменных, тогда как concat загроможден кавычками и знаками + и смущает мои глаза:
(Я позаимствовал пример Майка, потому что мне это нравится)
Если строка формата не имеет большого значения без имен переменных, я должен использовать concat:
Опция форматирования позволяет мне прочитать имена переменных и сопоставить их с соответствующими числами. Опция concat этого не требует. Меня все еще смущают кавычки и знаки +, но альтернатива хуже. Рубин?
С точки зрения производительности, я ожидаю, что параметр format будет медленнее, чем concat, поскольку форматирование требует разбора строки . Я не помню, чтобы мне приходилось оптимизировать такого рода инструкции, но если бы я это сделал, я бы посмотрел на
string
такие методы, какConcat()
иJoin()
.Другое преимущество формата заключается в том, что строку формата можно поместить в файл конфигурации. Очень удобно с сообщениями об ошибках и текстом пользовательского интерфейса.
источник
Я бы использовал String.Format, но у меня также была бы строка формата в файлах ресурсов, чтобы ее можно было локализовать для других языков. Использование простой строки concat не позволяет вам сделать это. Очевидно, что если вам никогда не понадобится локализовать эту строку, это не повод задуматься. Это действительно зависит от того, для чего предназначена строка.
Если это будет показано пользователю, я бы использовал String.Format, чтобы я мог локализовать, если мне нужно - и FxCop проверит его правописание, на всякий случай :)
Если он содержит числа или любые другие нестроковые объекты (например, даты), я бы использовал String.Format, потому что он дает мне больше контроля над форматированием .
Если бы это для построения запроса, как SQL, я бы использовал Linq .
Если бы для объединения строк внутри цикла, я бы использовал StringBuilder чтобы избежать проблем с производительностью.
Если это какой-то вывод, который пользователь не увидит и не повлияет на производительность, я бы использовал String.Format, потому что я все равно использую его и просто привык к нему :)
источник
Если вы имеете дело с чем-то, что должно быть легко читаемым (а это большая часть кода), я бы остановился на версии перегрузки оператора UNLESS:
По крайней мере при двух из этих обстоятельств я бы вместо этого использовал StringBuilder.
источник
Если вы намереваетесь локализовать результат, то String.Format необходим, потому что разные естественные языки могут даже не иметь данные в одном и том же порядке.
источник
Я думаю, что это сильно зависит от того, насколько сложным является выход. Я склонен выбирать тот сценарий, который работает лучше всего в то время.
Подберите правильный инструмент в зависимости от работы: D Какой из них выглядит чистым!
источник
Я предпочитаю и второе, но у меня нет рациональных аргументов в поддержку этого положения.
источник
Хороший!
Только что добавленное
И это даже быстрее (я думаю, что string.Concat вызывается в обоих примерах, но первый требует своего рода перевода).
источник
string.Concat(...)
. Это делается во время компиляции, поэтому не влияет на производительность во время выполнения. Если вы запускаете тесты несколько раз или запускаете тестовые образцы большего размера, вы увидите, что они идентичны.Поскольку я не думаю, что ответы здесь охватывают все, я хотел бы сделать небольшое дополнение здесь.
Console.WriteLine(string format, params object[] pars)
звонкиstring.Format
. «+» Подразумевает конкатенацию строк. Я не думаю, что это всегда связано со стилем; Я склонен смешивать два стиля в зависимости от контекста, в котором я нахожусь.Короткий ответ
Решение, с которым вы сталкиваетесь, связано с распределением строк. Я постараюсь сделать это просто.
Скажи, что у тебя есть
Если вы выполните это, он будет оцениваться следующим образом:
tmp
здесь на самом деле не локальная переменная, но она временная для JIT (она помещается в стек IL). Если вы помещаете строку в стек (например,ldstr
в IL для литералов), вы помещаете ссылку на указатель строки в стеке.В тот момент, когда вы звоните
concat
эту ссылку, возникает проблема, потому что нет ни одной доступной строковой ссылки, содержащей обе строки. Это означает, что .NET необходимо выделить новый блок памяти, а затем заполнить его двумя строками. Причина, по которой это проблема, заключается в том, что распределение относительно дорого.Что меняет вопрос на: Как вы можете уменьшить количество
concat
операций?Таким образом, грубый ответ:
string.Format
для> 1 конкатата '+' будет отлично работать для 1 конкатата. И если вы не заботитесь об оптимизации микропроцессора,string.Format
в общем случае все будет работать нормально.Записка о культуре
А потом есть что-то под названием культура ...
string.Format
позволяет использоватьCultureInfo
в вашем форматировании. Простой оператор «+» использует текущую культуру.Это особенно важное замечание, если вы пишете форматы файлов и f.ex.
double
значения, которые вы «добавляете» в строку. На разных машинах вы можете получить разные строки, если не используетеstring.Format
явныеCultureInfo
.F.ex. подумайте, что произойдет, если вы измените «.» для ',' при написании файла значений, разделенных запятыми ... на голландском языке десятичный разделитель - запятая, так что ваш пользователь может просто получить «забавный» сюрприз.
Более подробный ответ
Если вы заранее не знаете точный размер строки, лучше использовать такую политику, чтобы перераспределить используемые вами буферы. Сначала свободное место заполняется, после чего данные копируются в.
Увеличение означает выделение нового блока памяти и копирование старых данных в новый буфер. Старый блок памяти может быть освобожден. Вы получаете практический результат: выращивание - дорогостоящая операция.
Наиболее практичный способ сделать это - использовать политику перераспределения. Наиболее распространенной политикой является перераспределение буферов со степенями 2. Конечно, вы должны сделать это немного умнее этого (поскольку нет смысла расти с 1,2,4,8, если вы уже знаете, что вам нужно 128 символов) ) но вы получите картину. Политика гарантирует, что вам не нужно слишком много дорогих операций, которые я описал выше.
StringBuilder
это класс, который в основном перераспределяет основной буфер в степени два.string.Format
используетStringBuilder
под капотом.Это делает ваше решение основным компромиссом между overallocate-and-append (-multiple) (w / wo culture) или просто «распределить-и-добавить».
источник
Лично, второй, поскольку все, что вы используете, находится в прямом порядке, в котором он будет выводиться. Тогда как с первым вы должны сопоставить {0} и {1} с правильным var, что легко испортить.
По крайней мере, это не так плохо, как в C ++ sprintf, где, если вы неправильно указали тип переменной, все это взорвется.
Кроме того, поскольку второй является встроенным и не должен выполнять поиск и замену всех элементов {0}, последний должен быть быстрее ... хотя я точно не знаю.
источник
Мне на самом деле нравится первый, потому что, когда в тексте много переменных, мне кажется, что их легче читать. Кроме того, легче использовать кавычки при использовании строки. Формат () форматирования. Вот достойный анализ конкатенации строк.
источник
Я всегда шел по маршруту string.Format (). Возможность хранить форматы в переменных, как в примере Натана, является большим преимуществом. В некоторых случаях я могу добавить переменную, но как только объединяется более 1 переменной, я реорганизую использование форматирования.
источник
Да, и просто для полноты, следующее на несколько тиков быстрее обычной конкатенации:
источник
Первый (формат) выглядит лучше для меня. Это более читабельно, и вы не создаете дополнительные временные строковые объекты.
источник
Мне было любопытно, где StringBuilder стоял с этими тестами. Результаты ниже ...
Полученные результаты:
источник
Согласно подготовительному материалу MCSD, Microsoft предлагает использовать оператор + при работе с очень небольшим числом конкатенаций (вероятно, от 2 до 4). Я до сих пор не уверен, почему, но это то, что нужно учитывать.
источник