Marshal.PtrToStringUni () против новой строки ()? - PullRequest
7 голосов
/ 06 февраля 2010

Предположим, у меня есть указатель типа char * на строку Unicode, и я знаю длину:

char* _unmanagedStr;
int _unmanagedStrLength;

и у меня есть 2 способа преобразовать его в строку .NET:

Marshal.PtrToStringUni((IntPtr)_unmanagedStr, _unmanagedStrLength);

и

new string(_unmanagedStr, 0, _unmanagedStrLength);

В моих тестах оба вызова дают мне одинаковый результат, но new string() примерно в 1,8 раза быстрее, чем Marshal.PtrToStringUni().

Почему эта разница в производительности? Есть ли другое функциональное различие между ними?

Ответы [ 2 ]

9 голосов
/ 06 февраля 2010

Судя по доступному исходному коду (Rotor), конструктор System.String (Char *) использует сильно оптимизированный путь кода через CtorCharPtr (), он распределяет строку с помощью FastAllocateString (). Marshal.PtrToStringUni () следует совершенно другому пути кода, он написан на C ++ и выглядит так, что копирует строку дважды, без преимущества «быстрого выделения».

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

Не уверен, как это было бы полезно, используйте быстрый. Ошибки могут привести к аналогичному исключению в Windows.

8 голосов
/ 06 февраля 2010

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

...