Небезопасное создание строки из char [] - PullRequest
7 голосов
/ 12 января 2012

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

Вот что происходит в каком-то разделе:

  1. A string сканируется, и метаданные эффективно сохраняются.
  2. На основании этих метаданных фрагменты основной строки разделяются на char[][].
  3. То, что char[][] должно быть переведено в string[].

Теперь я знаю, что вы можете просто позвонить new string(char[]), но тогда результат нужно будет скопировать.

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

Я видел несколько способов достижения этого, но ни один из них меня не устраивал.

Есть ли у кого-нибудь верные предложения относительно того, как этого добиться?

Дополнительная информация:
Фактический процесс не включает в себя преобразование в char[] обязательно, это практически операция с несколькими подстроками. Как 3 индекса и их длины.

У StringBuilder слишком много служебной информации для небольшого числа concats.

EDIT:
В связи с некоторыми неясными аспектами того, что именно я спрашиваю, позвольте мне переформулировать это.

Вот что происходит:

  1. Основная строка проиндексирована.
  2. Части основной строки копируются в char[].
  3. char[] преобразуется в string.

Что я хотел бы сделать, это объединить шаги 2 и 3, в результате чего:

  1. Основная строка проиндексирована.
  2. Части основной строки копируются в string (и GC может держать его подальше от него во время процесса при правильном использовании ключевого слова fixed?).

И обратите внимание, что я не могу изменить тип вывода со строки [], поскольку это внешняя библиотека, и проекты зависят от нее (обратная совместимость).

Ответы [ 4 ]

2 голосов
/ 12 января 2012

Просто создайте свою собственную систему адресации вместо попытки использовать небезопасный код для сопоставления с внутренней структурой данных.

Отображение string (которое также читается как char[]) в массивменьшие строки ничем не отличаются от построения списка адресной информации (индекс и длина каждой подстроки).Поэтому создайте новый List<Tuple<int,int>> вместо string[] и используйте эти данные, чтобы получить правильную строку из исходной неизмененной структуры данных.Это может быть легко заключено во что-то, что разоблачает string[].

2 голосов
/ 12 января 2012

Что произойдет, если вы сделаете:

string s = GetBuffer();
fixed (char* pch = s) {
    pch[0] = 'R';
    pch[1] = 'e';
    pch[2] = 's';
    pch[3] = 'u';
    pch[4] = 'l';
    pch[5] = 't';
}

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

У вас есть данные профилировщика, чтобы показать, что StringBuilder недостаточно быстро для ваших целей, или это предположение?

2 голосов
/ 12 января 2012

Я думаю, что вы просите «разрезать» существующую строку на месте на несколько меньших строк без перераспределения массивов символов для меньших строк.Это не будет работать в управляемом мире.

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

РЕДАКТИРОВАТЬ: В отличие от выкалывания символов в ответе Бена (что умно, но ИМХО немного страшно), вы можете выделитьStringBuilder с предопределенной емкостью, что устраняет необходимость перераспределения внутренних массивов.Смотри http://msdn.microsoft.com/en-us/library/h1h0a5sy.aspx.

0 голосов
/ 12 января 2012

В .NET нет способа создать экземпляр String, который делит данные с другой строкой.Некоторое обсуждение, почему это появляется в этом комментарии от Эрика Липперта.

...