He estado trabajando con algunos programas aquí en el trabajo durante aproximadamente un mes que tienen un montón de análisis de cadenas y cosas así. Me han aconsejado usar una matriz de caracteres para estas cosas en lugar de una cadena porque la matriz de caracteres es más rápida. Entiendo por qué una matriz de caracteres es rápida, pero ¿qué tiene que ver con el tipo de cadena que la hace más lenta? ¿Qué estructura de datos está implementando y hay alguna manera de hacerlo tan rápido como una matriz de caracteres?tipo de cadena .NET frente a la matriz de caracteres
Respuesta
La diferencia más obvia es que string
es inmutable. Por lo tanto, no puede modificar partes de este y necesita crear una copia completamente nueva en cada modificación.
La cadena en sí tiene una implementación muy especial (es una clase de tamaño variable) y no está respaldada por una matriz. No veo ninguna razón por la que el acceso de solo lectura a char
s en una cadena sea lento.
Así que si quiere cambiar las partes pequeñas de una cadena, necesita usar StringBuilder
o char[]
. De estos dos char[]
es/era más rápido desde StringBuilder
tiene verificaciones e indirecciones adicionales. Pero como se trata de un detalle de implementación, podría haber cambiado desde la última vez que lo probé.
Justo como punto de referencia, y como de .NET 4 Configuración de un miembro de char[]
es aproximadamente cuatro veces más rápido en comparación con un StringBuilder
. Pero ambos pueden hacer más de 200 millones de asignaciones por segundo, por lo que rara vez importa en la práctica.
La lectura de un char[]
es un poco más rápida (25% para mi código de prueba) que la lectura de string
. La lectura de StringBuilder
por otro lado es más lenta (un factor de 3) que la lectura de char[]
.
En todos los puntos de referencia descuidé la sobrecarga de mi otro código. Esto significa que mi prueba subestima un poco las diferencias.
Mi conclusión es que mientras que char[]
es más rápido que las alternativas, solo importa si vas a superar los cientos de megabytes por segundo.
//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];
}
(Sí, sé que mi código de prueba no es muy buena, pero no creo que hace una gran diferencia.)
La ventaja de las matrices de caracteres sobre cadenas es que puede alterar las matrices de caracteres en su lugar; en C# las cadenas son inmutables, por lo que cualquier cambio crea un nuevo objeto en el montón con una versión modificada de la cadena. En una matriz de caracteres puede hacer muchos cambios sin asignar nada en el montón.
- 1. Eficiencia: matriz de caracteres frente a matriz int
- 2. matriz de caracteres a cadena hexadecimal C++
- 3. strtok - matriz de caracteres frente puntero char
- 4. asignar una matriz de caracteres a una cadena literal - C++
- 5. Convirtiendo de cadena de caracteres a una matriz de uint8_t?
- 6. caracteres cadena de acceso a JavaScript como matriz
- 7. Haskell obtiene matriz de caracteres de la cadena?
- 8. VBA: Velocidad de iteración de la matriz de variante frente a la matriz de tipo versus la colección sin clave
- 9. Vector frente a cadena
- 10. Inicialización matriz de caracteres con la cadena más pequeña literal
- 11. Convertir matriz int a matriz de caracteres
- 12. Extensión del módulo F # frente a la extensión de tipo
- 13. Al pasar matriz de cadenas de caracteres a la función
- 14. Asignación de una cadena de caracteres a una matriz de caracteres
- 15. cadena a la lista de caracteres
- 16. .NET clases parciales frente a la herencia
- 17. cadena con estructura de matriz a matriz
- 18. Numpy: comprobar matriz para el tipo de datos de cadena
- 19. Copiando contenido de cadenas a la matriz de caracteres
- 20. inicializador cadena literal para una matriz de caracteres
- 21. C++ pasando la matriz de caracteres a la función
- 22. serialización de refuerzo directo a la matriz de caracteres
- 23. MemoryStream frente a una matriz de bytes
- 24. ios agregar matriz a la matriz en el frente
- 25. parámetros de tipo frente a los genéricos
- 26. representación de gráficos: lista de adyacencia frente a la matriz
- 27. cadena "matriz" a la matriz verdadera
- 28. Cadena frente a una nueva clase de datos
- 29. convertir matriz de cadena a matriz de bytes
- 30. Separar cadena en una matriz de caracteres en C++
No es el aumento de rendimiento con cadenas en términos de memoria como todas las cuerdas están internados. – koumides
@koumides Solo se encuetran los literales y las cadenas en los que se interna explícitamente. – CodesInChaos