EDIT: Ahora que usted ha proporcionado un contexto más:
tratando de reproducir esto, no pude encontrar un cuello de botella en string.Length
en absoluto. La única forma de hacerlo más rápido fue comentar la prueba y el cuerpo del bloque if, lo cual no es realmente justo. El solo hecho de comentar la condición aminoró la velocidad, es decir, la copia incondicional de la referencia fue más lenta que la comprobación de la condición.
Como se ha señalado, usar la sobrecarga de string.Split
que elimina las entradas vacías para usted es la verdadera optimización extrema.
Puede ir más lejos, evitando crear una nueva matriz de caracteres con solo un espacio en todo momento. Siempre pasarás lo mismo de manera efectiva, ¿por qué no aprovechar eso?
Los arreglos vacíos son efectivamente inmutables. Puede optimizar el caso nulo/vacío siempre devolviendo lo mismo.
El código optimizado se convierte en:
private static readonly char[] Delimiters = " ".ToCharArray();
private static readonly string[] EmptyArray = new string[0];
public static string[] SplitOnMultiSpaces(string text)
{
if (string.IsNullOrEmpty(text))
{
return EmptyArray;
}
return text.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries);
}
String.Length
no hace absolutamente no contar las cartas en la cadena. El valor se almacena como un campo, aunque parece recordar que el bit superior de ese campo se utiliza para recordar si todos los caracteres son o no ASCII (o solían serlo, de todos modos) para permitir otras optimizaciones. Así que el acceso a la propiedad puede necesitar una máscara de bits, pero seguirá siendo O (1) y yo esperaría que el JIT también lo alinee. (Se implementó como extern
, pero con suerte eso no afectaría al JIT en este caso; sospecho que es una operación lo suficientemente común como para tener soporte especial).
Si ya sabe que la cadena no es nula, entonces su prueba existente de
if (s.Length != 0)
es el mejor camino a seguir si usted está buscando un rendimiento bruto de la OMI. Personalmente en la mayoría de los casos me gustaría escribir:
if (s != "")
para hacerlo más claro que no estamos tan interesados en la longitud como un valor que si es o no es una cadena vacía. Eso será un poco más lento que la prueba de longitud, pero creo que es más claro. Como siempre, iría por el código más claro hasta que tenga datos de referencia/perfil para indicar que esto realmente es un cuello de botella. Sé que su pregunta es explícitamente sobre encontrar la prueba más eficiente, pero pensé que mencionaría esto de todos modos. ¿Tiene evidencia de que este es un cuello de botella?
EDIT: Sólo para dar razones claras para mi sugerencia de no usando string.IsNullOrEmpty
: una llamada a ese método me sugiere que la persona está tratando de forma explícita para tratar el caso en que la variable es nula, de lo contrario wouldn' lo he mencionado. Si en este punto del código cuenta como un error si la variable es nula, entonces no debería tratar de manejarla como un caso normal.
En esta situación, el cheque Length
es en realidad mejor de una manera que la prueba de la desigualdad que he sugerido: actúa como una afirmación implícita de que la variable no es nulo. Si tiene un error y es nulo, la prueba lanzará una excepción y el error se detectará temprano. Si usa la prueba de igualdad, considerará nulo como diferente a la cadena vacía, por lo que irá a su cuerpo de declaración "si". Si usa string.IsNullOrEmpty
, considerará que null es lo mismo que vacío, por lo que no entrará en el bloque.
¡El problema de perf que enfrenta es muy probable que se resuelva en otro lugar! ¿Hiciste un perfil y descubriste que el cuello de botella realmente está aquí? –
¿Por curiosidad a qué versión del marco está apuntando? –
** NOTA ** para otros posibles contendientes: Eric ha publicado una respuesta que aclara su pregunta (un poco) a continuación ... –