строковый тип .NET или массив символов - PullRequest
9 голосов
/ 11 июля 2011

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

Ответы [ 2 ]

15 голосов
/ 11 июля 2011

Самое очевидное отличие состоит в том, что string является неизменным. Таким образом, вы не можете изменять его части, и вам нужно создавать абсолютно новую копию для каждой модификации.

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

Поэтому, если вы хотите изменить небольшие части строки, вам нужно использовать либо StringBuilder, либо char[]. Из этих двух char[] быстрее / быстрее, так как StringBuilder имеет дополнительные проверки и косвенные указания. Но поскольку это деталь реализации, она могла измениться с тех пор, как я в последний раз проверял.


Просто протестировал его, и начиная с .NET 4 установка члена char[] примерно в четыре раза быстрее по сравнению с StringBuilder. Но оба могут выполнять более 200 миллионов заданий в секунду, поэтому на практике это редко имеет значение.

Чтение с char[] немного быстрее (25% для моего тестового кода), чем с string. С другой стороны, чтение из StringBuilder медленнее (в 3 раза), чем чтение из char[].

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

Мой вывод таков: хотя char[] быстрее, чем альтернативы, это имеет значение, только если вы используете сотни мегабайт в секунду.


//Write StringBuilder
StringBuilder sb = new StringBuilder();
sb.Length = 256;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sb[j] = 'A';
}

//Write char[]
char[] cs = new char[256];
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    cs[j] = 'A';
}

// Read string
string s = new String('A',256);
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

//Read char[]
char[] s = new String('A',256).ToCharArray();
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

//Read StringBuilder
StringBuilder s= new StringBuilder(new String('A',256));
int sum = 0;
for(int i=0; i<1000000000; i++)
{
    int j = i&255;
    sum += s[j];
}

(Да, я знаю, что мой тестовый код не очень хорош, но я не думаю, что это имеет большое значение.)

2 голосов
/ 11 июля 2011

Преимущество массивов символов перед строками заключается в том, что вы можете изменять массивы символов на месте; в C # строки являются неизменяемыми, и поэтому любое изменение создает новый объект в куче с измененной версией строки. В массиве char вы можете вносить множество изменений, не выделяя ничего в куче.

...