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 :)
Hola, Allen, ¡muchas gracias! – abatishchev