programming code string optimization language-agnostic compiler-construction

string - code - interpreter programming



¿Está buscando contenido de cuerdas? cadena Longitud Vs Empty String (13)

En este caso, la comprobación directa de la longitud es más rápida, ya que evita la sobrecarga de la construcción de la nueva cadena vacía.

@DerekPark: Eso no siempre es verdad. "" es un literal de cadena, por lo que, en Java, seguramente ya estará internado.

¿Cuál es más eficiente para el compilador y la mejor práctica para verificar si una cadena está en blanco?

  1. Comprobando si la longitud de la cadena == 0
  2. Comprobando si la cadena está vacía (strVar == "")

Además, ¿la respuesta depende del lenguaje?


En los idiomas que usan cadenas estilo C (terminadas en nulo), la comparación con "" será más rápida

En realidad, puede ser mejor verificar si el primer carácter de la cadena es ''/ 0'':

char *mystring; /* do something with the string */ if ((mystring != NULL) && (mystring[0] == ''/0'')) { /* the string is empty */ }

En Perl hay una tercera opción, que la cadena no está definida. Esto es un poco diferente de un puntero NULL en C, aunque solo sea porque no se obtiene un error de segmentación para acceder a una cadena indefinida.


@ Nathan

En realidad, puede ser mejor verificar si el primer carácter de la cadena es ''/ 0'':

Casi lo mencioné, pero terminé dejándolo fuera, ya que llamar a strcmp() con la cadena vacía y verificar directamente el primer carácter de la cadena son ambos O (1). Básicamente, solo paga por una llamada de función extra, que es bastante barata. Sin embargo, si realmente necesita la mejor velocidad absoluta, definitivamente vaya con una comparación directa de primer char a 0.

Honestamente, siempre uso strlen() == 0 , porque nunca escribí un programa donde este era en realidad un problema de rendimiento medible, y creo que es la forma más legible de expresar el cheque.


En Java 1.6, la clase String tiene un nuevo método isEmpty

También está la biblioteca de Jakarta commons, que tiene el método isBlank . Blanco se define como una cadena que contiene solo espacios en blanco.


En la red:

string.IsNullOrEmpty( nystr );

las cadenas pueden ser nulas, por lo que .Long a veces arroja una NullReferenceException


En los idiomas que usan cadenas estilo C (terminadas en nulo), la comparación con "" será más rápida. Esa es una operación O (1), mientras que tomar la longitud de una cadena de estilo C es O (n).

En los idiomas que almacenan la longitud como parte del objeto de cadena (C #, Java, ...), la longitud también es O (1). En este caso, la comprobación directa de la longitud es más rápida, ya que evita la sobrecarga de la construcción de la nueva cadena vacía.



Para C cadenas,

if (s[0] == 0)

será más rápido que cualquiera

if (strlen(s) == 0)

o

if (strcmp(s, "") == 0)

porque evitará la sobrecarga de una llamada a función.


Nuevamente, sin saber el idioma, es imposible saberlo.

Sin embargo, le recomiendo que elija la técnica que tenga más sentido para el programador de mantenimiento que le sigue y deberá mantener su trabajo.

Recomiendo escribir una función que haga explícitamente lo que quieras, como

#define IS_EMPTY(s) ((s)[0]==0)

o comparable. Ahora no hay dudas en que lo estás verificando.


Suponiendo que tu pregunta es .NET:

Si también quiere validar su cadena contra la nulidad, use IsNullOrEmpty, si ya sabe que su cadena no es nula, por ejemplo al verificar TextBox.Text, etc., no use IsNullOrEmpty, y luego aparece en su pregunta.
Entonces, para mi opinión, String.Length es menos rendimiento que la comparación de cadenas.

El evento lo probé (también probé con C #, el mismo resultado):

Module Module1 Sub Main() Dim myString = "" Dim a, b, c, d As Long Console.WriteLine("Way 1...") a = Now.Ticks For index = 0 To 10000000 Dim isEmpty = myString = "" Next b = Now.Ticks Console.WriteLine("Way 2...") c = Now.Ticks For index = 0 To 10000000 Dim isEmpty = myString.Length = 0 Next d = Now.Ticks Dim way1 = b - a, way2 = d - c Console.WriteLine("way 1 took {0} ticks", way1) Console.WriteLine("way 2 took {0} ticks", way2) Console.WriteLine("way 1 took {0} ticks more than way 2", way1 - way2) Console.Read() End Sub End Module

Resultado:

Way 1... Way 2... way 1 took 624001 ticks way 2 took 468001 ticks way 1 took 156000 ticks more than way 2

Lo que significa que la comparación toma mucho más tiempo que la verificación de la longitud de la cadena.


Después de leer este hilo, realicé un pequeño experimento, que arrojó dos hallazgos distintos e interesantes.

Considera lo siguiente.

strInstallString "1" string

Lo anterior se copia de la ventana local del depurador de Visual Studio. El mismo valor se usa en los tres ejemplos siguientes.

if (strInstallString == "") === if (strInstallString == string.Empty)

A continuación se muestra el código que se muestra en la ventana de desensamblaje del depurador de Visual Studio 2013 para estos dos casos fundamentalmente idénticos.

if ( strInstallString == "" ) 003126FB mov edx,dword ptr ds:[31B2184h] 00312701 mov ecx,dword ptr [ebp-50h] 00312704 call 59DEC0B0 ; On return, EAX = 0x00000000. 00312709 mov dword ptr [ebp-9Ch],eax 0031270F cmp dword ptr [ebp-9Ch],0 00312716 sete al 00312719 movzx eax,al 0031271C mov dword ptr [ebp-64h],eax 0031271F cmp dword ptr [ebp-64h],0 00312723 jne 00312750 if ( strInstallString == string.Empty ) 00452443 mov edx,dword ptr ds:[3282184h] 00452449 mov ecx,dword ptr [ebp-50h] 0045244C call 59DEC0B0 ; On return, EAX = 0x00000000. 00452451 mov dword ptr [ebp-9Ch],eax 00452457 cmp dword ptr [ebp-9Ch],0 0045245E sete al 00452461 movzx eax,al 00452464 mov dword ptr [ebp-64h],eax 00452467 cmp dword ptr [ebp-64h],0 0045246B jne 00452498

if (strInstallString == string.Empty) No es significativamente diferente

if ( strInstallString.Length == 0 ) 003E284B mov ecx,dword ptr [ebp-50h] 003E284E cmp dword ptr [ecx],ecx 003E2850 call 5ACBC87E ; On return, EAX = 0x00000001. 003E2855 mov dword ptr [ebp-9Ch],eax 003E285B cmp dword ptr [ebp-9Ch],0 003E2862 setne al 003E2865 movzx eax,al 003E2868 mov dword ptr [ebp-64h],eax 003E286B cmp dword ptr [ebp-64h],0 003E286F jne 003E289C

De los listados de códigos de máquina anteriores, generados por el módulo NGEN de .NET Framework, versión 4.5, saco las siguientes conclusiones.

  1. Prueba de igualdad contra el literal de cadena vacía y la cadena estática. La propiedad vacía de la clase System.string es, para todos los fines prácticos, idéntica. La única diferencia entre los dos fragmentos de código es la fuente de la primera instrucción de movimiento, y ambos son desplazamientos relativos a ds, lo que implica que ambos se refieren a las constantes de cocción al horno.

  2. Probar la igualdad contra la cadena vacía, ya sea como una propiedad literal o string.Empty, configura una llamada a función de dos argumentos, que indica la desigualdad al devolver cero. Baso esta conclusión en otras pruebas que realicé hace un par de meses, en las que seguí parte de mi propio código a través de la división gestionada / no gestionada y viceversa. En todos los casos, cualquier llamada que requiera dos o más argumentos colocará el primer argumento en el registro ECX, y el segundo en el registro EDX. No recuerdo cómo se aprobaron los argumentos posteriores. Sin embargo, la configuración de la llamada se parecía más a __fastcall que __stdcall. Del mismo modo, los valores esperados de retorno siempre aparecían en el registro EAX, que es casi universal.

  3. Al probar la longitud de la cadena se configura una llamada de función de un argumento, que devuelve 1 (en el registro EAX), que es la longitud de la cadena que se está probando.

  4. Dado que el código de máquina inmediatamente visible es casi idéntico, la única razón que puedo imaginar que explicaría el mejor rendimiento de la igualdad de cuerdas sobre la longitud de aguijón informado por Shinny es que la función de dos argumentos que realiza la comparación es significativamente mejor optimizado que la función de un argumento que lee la longitud de la instancia de cadena.

Conclusión

Como una cuestión de principio, evito comparar contra la cadena vacía como un literal, porque el literal de la cadena vacía puede parecer ambiguo en el código fuente. Para ese fin, mis clases de ayuda .NET han definido la cadena vacía como una constante. Aunque uso string.Empty para comparaciones directas, en línea, la constante gana su mantenimiento para definir otras constantes cuyo valor es la cadena vacía, porque una constante no puede asignarse a la cadena . Vacío como su valor.

Este ejercicio resuelve, de una vez por todas, cualquier preocupación que pueda tener sobre el costo, si lo hay, de comparar con cualquiera de las cadenas. Vacío o la constante definida por mis clases de ayuda.

Sin embargo, también plantea una pregunta desconcertante para reemplazarlo; ¿Por qué es comparar contra cadena. Vacío más eficiente que probar la longitud de la cadena? ¿O la prueba utilizada por Shinny es invalidada debido a la forma en que se implementa el ciclo? (Me resulta difícil de creer, pero, una vez más, me han engañado antes, ¡y estoy seguro de que tú también!)

Durante mucho tiempo asumí que los objetos system.string se contaban cadenas, fundamentalmente similares a la cadena básica largamente establecida (BSTR) que conocemos desde hace mucho tiempo por COM.


Sí, depende del idioma, ya que el almacenamiento de cadenas difiere entre los idiomas.

  • Cadenas tipo Pascal: Length = 0 .
  • Cadenas estilo C: [0] == 0 .
  • .NET: .IsNullOrEmpty .

Etc.


String.IsNullOrEmpty() solo funciona en .net 2.0 y superior, para .net 1 / 1.1, tiendo a usar:

if (inputString == null || inputString == String.Empty) { // String is null or empty, do something clever here. Or just expload. }

Uso String.Empty en lugar de "" porque "" creará un objeto, mientras que String.Empty no - sé que es algo pequeño y trivial, pero aún así id no creo objetos cuando no los necesito. ( Fuente )