Я знаю, что этот вопрос был был сделан , но у меня есть немного другой поворот к нему. Некоторые отметили, что это преждевременная оптимизация, что совершенно верно, если бы я просил только практичности и практичности. Моя проблема коренится в практической проблеме, но мне все равно любопытно.
Я создаю кучу операторов SQL для создания сценария (так как он будет сохранен на диске) для воссоздания схемы базы данных (легко много сотен таблиц, представлений и т. Д.). Это означает, что моя конкатенация строк только для добавления. StringBuilder, согласно MSDN, работает путем сохранения внутреннего буфера (обязательно char []) и копирования в него строковых символов и перераспределения массива по мере необходимости.
Однако в моем коде много повторяющихся строк ("CREATE TABLE [", "GO \ n" и т. Д.), Что означает, что я могу использовать их , будучи интернированным , но не при использовании StringBuilder, так как они будут копироваться каждый раз. Единственными переменными являются имена таблиц и такие, которые уже существуют в виде строк в других объектах, которые уже находятся в памяти.
Итак, насколько я могу судить, что после считывания моих данных и создания моих объектов, содержащих информацию о схеме, вся моя строковая информация может быть повторно использована интернированием, да?
Предполагая, что тогда не будет List или LinkedList строк быстрее, потому что они сохраняют указатели на интернированные строки? Тогда это только один вызов String.Concat () для одного выделения памяти всей строки, которая в точности соответствует правильной длине.
Список должен был бы перераспределить строку [] интернированных указателей, а связанный список должен был бы создать узлы и изменить указатели, поэтому они не "свободны", но если я объединяю многие тысячи интернированные строки тогда они могут показаться более эффективными.
Теперь я полагаю, что мог бы придумать эвристический подсчет символов для каждого оператора SQL, подсчитать каждый тип, получить приблизительное представление и предварительно настроить емкость моего StringBuilder, чтобы избежать перераспределения его символа [], но мне пришлось бы выполнить перебор по справедливая маржа для уменьшения вероятности перераспределения.
Таким образом, для этого случая, который будет быстрее всего получить одну объединенную строку:
- StringBuilder
- Список внутренних строк
- LinkedList внутренних строк
- StringBuilder с эвристической емкостью
- Что-то еще?
Как отдельный вопрос (я не всегда обращаюсь к диску) на вышеприведенный вопрос: будет ли еще один StreamWriter для выходного файла быстрее? В качестве альтернативы используйте List или LinkedList, а затем запишите их в файл из списка вместо того, чтобы сначала объединить в памяти.
EDIT:
По запросу ссылка (.NET 3.5) на MSDN. Он говорит: "Новые данные добавляются в конец буфера, если доступно пространство; в противном случае выделяется новый, больший буфер, данные из исходного буфера копируются в новый буфер, затем новые данные добавляются в новый буфер. " Это для меня означает char [], который перераспределяется, чтобы сделать его больше (который требует копирования старых данных в массив с измененным размером) и затем добавляет.