2009-08-19 12 views
5

Antecedentes¿Puedo comparar el código IL para determinar qué técnica es más rápida o mejor?

This question me hizo pensar acerca de algo. Últimamente, desde que he estado buscando linq pad 's funcionalidad IL, he estado comparando el código IL de dos enfoques para el mismo problema para "determinar" cuál es el mejor.

Uso de la cuestión vinculada a arriba, sobre la conversión de una matriz, me genera el código IL para las dos respuestas:

var arr = new string[] { "1", "2", "3", "4" }; 
var result = Array.ConvertAll(arr, s => Int32.Parse(s)); 

producido:

IL_0001: ldc.i4.4  
IL_0002: newarr  System.String 
IL_0007: stloc.2  
IL_0008: ldloc.2  
IL_0009: ldc.i4.0  
IL_000A: ldstr  "1" 
IL_000F: stelem.ref 
IL_0010: ldloc.2  
IL_0011: ldc.i4.1  
IL_0012: ldstr  "2" 
IL_0017: stelem.ref 
IL_0018: ldloc.2  
IL_0019: ldc.i4.2  
IL_001A: ldstr  "3" 
IL_001F: stelem.ref 
IL_0020: ldloc.2  
IL_0021: ldc.i4.3  
IL_0022: ldstr  "4" 
IL_0027: stelem.ref 
IL_0028: ldloc.2  
IL_0029: stloc.0  
IL_002A: ldloc.0  
IL_002B: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0030: brtrue.s IL_0045 
IL_0032: ldnull  
IL_0033: ldftn  b__0 
IL_0039: newobj  System.Converter<System.String,System.Int32>..ctor 
IL_003E: stsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0043: br.s  IL_0045 
IL_0045: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_004A: call  System.Array.ConvertAll 
IL_004F: stloc.1  

b__0: 
IL_0000: ldarg.0  
IL_0001: call  System.Int32.Parse 
IL_0006: stloc.0  
IL_0007: br.s  IL_0009 
IL_0009: ldloc.0  
IL_000A: ret   

y la otra respuesta:

var arr = new string[] { "1", "2", "3", "4" }; 
var result = arr.Select(s => int.Parse(s)).ToArray(); 

producido:

IL_0001: ldc.i4.4  
IL_0002: newarr  System.String 
IL_0007: stloc.2  
IL_0008: ldloc.2  
IL_0009: ldc.i4.0  
IL_000A: ldstr  "1" 
IL_000F: stelem.ref 
IL_0010: ldloc.2  
IL_0011: ldc.i4.1  
IL_0012: ldstr  "2" 
IL_0017: stelem.ref 
IL_0018: ldloc.2  
IL_0019: ldc.i4.2  
IL_001A: ldstr  "3" 
IL_001F: stelem.ref 
IL_0020: ldloc.2  
IL_0021: ldc.i4.3  
IL_0022: ldstr  "4" 
IL_0027: stelem.ref 
IL_0028: ldloc.2  
IL_0029: stloc.0  
IL_002A: ldloc.0  
IL_002B: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0030: brtrue.s IL_0045 
IL_0032: ldnull  
IL_0033: ldftn  b__0 
IL_0039: newobj  System.Func<System.String,System.Int32>..ctor 
IL_003E: stsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_0043: br.s  IL_0045 
IL_0045: ldsfld  UserQuery.CS$<>9__CachedAnonymousMethodDelegate1 
IL_004A: call  System.Linq.Enumerable.Select 
IL_004F: call  System.Linq.Enumerable.ToArray 
IL_0054: stloc.1  

b__0: 
IL_0000: ldarg.0  
IL_0001: call  System.Int32.Parse 
IL_0006: stloc.0  
IL_0007: br.s  IL_0009 
IL_0009: ldloc.0  
IL_000A: ret  

En cuanto a esto, todo lo que puedo decir es que esta última opción

  • toma 1 línea adicional
  • utiliza LINQ cuando la primera respuesta no hace
  • crea de la Int manera diferente a través de IL_0039.

Preguntas

  • Para este ejemplo específico, son mis suposiciones correcta?
  • En general, ¿cómo debo hacer para comparar dos soluciones a través del código IL?
  • En general, ¿una solución con menos IL LOC significa que será más rápido o usará menos memoria?
  • Como dice el título, ¿Puedo comparar el código IL para determinar qué técnica es más rápida o mejor?

FWIW, no hago esto a menudo, solo de vez en cuando, cuando surge una discusión entre los desarrolladores en el trabajo. Alguien dirá "oh esto es más eficiente" y lo lanzaremos a linqpad para ver el código IL. También FWIW, casi siempre cumplo con que funcione antes de lograr un enfoque eficiente/rápido. Sólo para que la gente no piensa que estoy comparando constantemente código IL de lo que estoy desarrollando :)

+0

Hola, Allen, ¡muchas gracias! – abatishchev

Respuesta

8
  • Para este ejemplo específico, son correctas mis suposiciones?
  • En general, ¿cómo debo hacer para comparar dos soluciones a través del código IL?
  • En general, ¿una solución con menos IL LOC significa que será más rápido o usará menos memoria?
  • Como dice el título, ¿Puedo comparar el código IL para determinar qué técnica es más rápida o mejor?

1) Sus suposiciones son correctas sobre lo que está sucediendo.

2) Es necesario comprender lo que el código IL está haciendo con el fin de determinar cuál es la "mejor"

3) No, significa que se necesita menos instrucciones a ejecutar. Sin embargo, estas instrucciones individuales pueden usar más memoria o menos. Por ejemplo, la instrucción a la que se refería, en un caso, es crear un delegado Func y, en el otro, crear un objeto Convertidor. Sin más información, es difícil saber cuál de esas dos cosas es más costosa.

4) Sí y no ....

El problema es que el código IL le dirá lo que está pasando, pero en realidad las llamadas anidadas en IL que van a ser el motor de gran rendimiento. Si el código IL está haciendo operaciones simples en todas partes, en general, cuanto más corto, mejor (aunque las operaciones individuales de IL pueden variar en velocidad, ellas mismas). Cuando el código llama a métodos o constructores de otros tipos, como el suyo, esto se vuelve imposible de decir solo. Una línea de IL puede llevar más tiempo en un caso (por ejemplo, llamar a un método costoso) que 50 en otro caso (donde están haciendo operaciones simples).

En su caso anterior, por ejemplo, las primeras 20 operaciones son muy, muy rápidas, mientras que las últimas toman casi todo su tiempo de ejecución.

+0

Interesante, pensé que mostraría todas las llamadas de IL anidadas, ¡gracias por la gran respuesta! Como una pregunta complementaria, ¿sabes dónde puedo obtener más información sobre IL o si debería preocuparme demasiado por ello? Lo siento, sé que esas preguntas son un poco complicadas. –

+2

Para entender realmente IL, comienza a leer la teoría de compiladores y/o el lenguaje ensamblador. Ayuda mucho a entender lo que está haciendo. De lo contrario, las secciones de MSDN en Reflection.Emit tienen mucha información buena. –

3

El fragmento del trabajo para ambas respuestas se hace en IL 004A (y IL 004F para el segundo). A menos que sepa el costo de estas llamadas externas, no hay ninguna base práctica sobre la cual pueda comparar el rendimiento de las dos respuestas.

Cuestiones relacionadas