Почему Строка. Concat, не оптимизированный к StringBuilder. Добавить?

Вам необходимо закрыть теги tbody , tr и td . Чтобы узнать больше о таблицах: https://www.w3schools.com/html/html_tables.asp

21
задан shA.t 16 September 2018 в 11:26
поделиться

8 ответов

Определенный ответ должен прийти от команды дизайна компилятора. Но позвольте мне взять удар здесь ...

Если ваш вопрос, почему компилятор не включает это:

string s = "";
for( int i = 0; i < 100; i ++ )
    s = string.Concat( s, i.ToString() );

в это:

StringBuilder sb = new StringBuilder();
for( int i = 0; i < 100; i++ )
    sb.Append( i.ToString() );
string s = sb.ToString();

наиболее вероятный ответ состоит в том, что это не оптимизация . Это переписать код, который вводит новые конструкции, основанные на знаниях и намерении, что разработчик имеет - не компилятор.

Этот тип изменений потребует компилятора, чтобы иметь больше знания BCL, чем уместно. Что если завтра, может быть доступна еще одна оптимальная служба сборки строки? Должен ли компилятор использовать это?

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

Наконец, я не уверен, что во всех случаях это приведет к более быстрому выполнению кода. Существует затрата для создания конструкции StringBuilder и изменением его внутреннего буфера в виде текста. На самом деле, стоимость добавления сильно привязана к размеру соединения строки, сколько существует, то, как выглядит давление памяти. Это вещи, которые компилятор не могут предсказать заранее.

Это ваша работа в качестве разработчика для записи хорошо выполняющего код. Компилятор может помочь только путем обеспечения определенного безопасного , инвариантных оптимизаций. Не переписать свой код для вас.

41
ответ дан 29 November 2019 в 06:10
поделиться

Две причины:

  • Вы не можете программно определить места, где это будет строго выше.
  • «Оптимизация» будет замедлять работу, если выполняется неправильно.

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

Редактировать: Что касается отсечки, у нас есть еще пара проблем:

  • Единственный способ узнать точно , что отсечка достигнута, это сложный анализ потока. Количество мест, где можно найти разделы, которые можно преобразовать, чрезвычайно мало.
  • Анализ потока дорог. Если вы сделаете это во время выполнения, вся программа будет работать медленнее из-за редкой вероятности того, что один фрагмент плохо написанного кода будет быстрее. Если вы делаете это во время компиляции, это не ошибка в соответствии с синтаксисом языка, но вы можете выдать предупреждение - и это именно то, что делает FXCop (медленный, но доступный инструмент анализа потока). Подумайте, всегда ли FXCop должен был работать с компилятором; столько часов люди будут просто ждать запуска кода. И если это было во время выполнения, добро пожаловать во времена запуска JVM ...
6
ответ дан 29 November 2019 в 06:10
поделиться

Re Ваше решение, мне пришлось сделать настройку, чтобы увидеть его работать для меня - вместо вашего контента ETC / FSTAB я использовал этот контент с указанной вами темы форума:

none /cygdrive cygdrive binary,posix=0,user,noacl 0 0

Я использую установщик 4.0. 3 Я достаточно счастлив, что это работает для меня, но я не могу предложить причину, почему, не быть достаточно знакомым с FSTAB-синтаксисом и вариантами. Надеюсь, это добавляет что-то полезное для кого-то другого.

-121--2980901-

Поскольку задание компилятора для генерации семантически правильного кода. Изменение вызовов string.concat к завозам StringBuilder.Append будет изменять семантику кода.

2
ответ дан 29 November 2019 в 06:10
поделиться

Ответ LBuskin отличный; мне нужно добавить пару вещей.

Во-первых, JScript.NET делает эту оптимизацию. JScript часто используется менее опытными программистами для задач, связанных с построением больших строк в циклах, таких как построение JSON-объектов, HTML-данных и так далее.

Поскольку эти программисты могут не знать о n-квадратичной стоимости наивного распределения строк, могут не знать о существовании строковых конструкторов и часто пишут код по этому паттерну, мы посчитали целесообразным поместить эту оптимизацию в JScript.NET.

Программисты на C#, как правило, больше знают о стоимости кода, который они пишут, и больше знают о существовании таких готовых частей, как StringBuilder, поэтому они меньше нуждаются в такой оптимизации. И что более фундаментально, философия дизайна C# заключается в том, что это язык "делай то, что я сказал" с минимумом "магии"; JScript - это язык "делай то, что я имею в виду", который делает все возможное, чтобы понять, как лучше всего обслужить тебя, даже если это означает иногда неправильные догадки. Обе философии справедливы и полезны.

Иногда она "идет другим путем". Сравните этот выбор с выбором, который мы делаем для включения строк. Включения строк на самом деле компилируются как создание словаря, содержащего строки, а не как серия сравнений строк. Эта оптимизация может быть плохой, может быть быстрее просто провести сравнение строк. Но здесь мы делаем предположение, что вы "имели в виду" переключатель, чтобы быть поиском таблицы, а не серией операторов "if" - если бы вы имели в виду серию операторов "if", вы могли бы легко написать это самостоятельно.

30
ответ дан 29 November 2019 в 06:10
поделиться

Для одного конкатенирования нескольких строк (например, a + b + c + d + e + f + g + h + i + j) вы действительно хотите, чтобы использовали String.Concat IMO. Он имеет накладные расходы, связанные с построением массива для каждого вызова, но его преимущество заключается в том, что метод может вычислить точную длину результирующей строки до того, как ему понадобится выделить какую-либо память. StringBuilder.Append(a).Append(b).... дает только одно значение за раз, поэтому конструктор не знает, сколько памяти нужно выделить.

Что касается выполнения этого в циклах - в этот момент добавлена новая локальная переменная, и нужно добавить код для записи обратно в строковую переменную в нужное время (вызов StringBuilder.ToString()). Что происходит при запуске в отладчике? Не будет ли непонятно, если не увидеть, как строится значение, становящееся видимым только в конце цикла? О, и конечно, вы должны выполнить соответствующую проверку, что значение не используется ни в одной точке до конца цикла...

16
ответ дан 29 November 2019 в 06:10
поделиться

Я считаю, что это будет немного сложнее для писателей компилятора. И когда вы ссылаетесь на промежуточные строки внутри петлей, помимо конкатенации (например, передача их в некоторые другие методы или около того), эта оптимизация не будет возможна.

1
ответ дан 29 November 2019 в 06:10
поделиться

Строка представляет собой неизменяемый тип, поэтому использование объединения строки медленнее, чем использование StringBuilder.Append .

Редактировать: Чтобы уточнить мою точку немного больше, когда вы говорите о том, почему String.concat не оптимизирован на StringBuilder.append , StringBuilder Класс имеет совершенно другую семантику к неизменному типу строки . Почему вы должны ожидать, что компилятор оптимизирует, что, как они явно разные вещи? Кроме того, StringBuilder - это музейный тип, который может динамически изменить его длину, зачем компилятор оптимизировать неизменяемый тип к смешанному типу? Это дизайн и семантика, уклоняемые в спецификации ECMA для .NET Framework, независимо от языка.

Это немного, как просить компилятора (и, возможно, ждать слишком много) для компиляции Char и оптимизировать его в INT , потому что int работает на 32 бита вместо 8 битов и будет считаться быстрее!

-2
ответ дан 29 November 2019 в 06:10
поделиться

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

Для объединения известного набора строк StringBuilder не быстрее, чем String.Concat .

0
ответ дан 29 November 2019 в 06:10
поделиться
Другие вопросы по тегам:

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