c# performance release inline inline-code

C#: ¿Por qué una llamada de función es más rápida que la alineación manual?



performance release (3)

He medido el tiempo de ejecución para dos formas de calcular la potencia de 2:

1) en línea

result = b * b;

2) Con una simple función de llamada.

result = Power(b);

Cuando se ejecuta en modo de depuración, todo es como se esperaba: Llamar a una función es considerablemente más costoso que hacer el cálculo en línea (385 ms en línea frente a 570 ms de llamada de función).

En el modo de lanzamiento, esperaría que el compilador acelerara considerablemente el tiempo de ejecución de la llamada a la función porque el compilador incorporaría internamente la muy pequeña función Power() . Pero NO esperaría que la llamada a la función sea MÁS RÁPIDA que el cálculo en línea manual.

Lo más sorprendente es que este es el caso: en la versión de lanzamiento, la primera ejecución necesita 109 ms y la segunda ejecución con la llamada a Power() solo necesita 62 ms.

¿Cómo puede una llamada a la función ser más rápida que la alineación manual?

Aquí está el programa para su reproducción:

class Program { static void Main(string[] args) { Console.WriteLine("Starting Test"); // 1. Calculating inline without function call Stopwatch sw = Stopwatch.StartNew(); for (double d = 0; d < 100000000; d++) { double res = d * d; } sw.Stop(); Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); // 2. Calulating power with function call Stopwatch sw2 = Stopwatch.StartNew(); for (int d = 0; d < 100000000; d++) { double res = Power(d); } sw2.Stop(); Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); Console.ReadKey(); } static double Power(double d) { return d * d; } }


Como Xavier descubrió correctamente, estás utilizando el doble en un bucle y el int en el otro. Cambiar ambos al mismo tipo hará que los resultados sean iguales, lo probé.

Además: lo que realmente estás midiendo aquí es la duración de las adiciones y comparaciones. No está midiendo la duración de la cuadratura de d , porque simplemente no está sucediendo: en una versión de lanzamiento, el optimizador elimina completamente el cuerpo del bucle, porque el resultado no se utiliza. Puedes confirmarlo comentando el cuerpo del bucle. La duración será la misma.


Daniel Hilgarth tiene razón, el cálculo no se realiza en absoluto, ya que el resultado no se utiliza (lo que probablemente no sea el caso en el modo de depuración). Prueba el siguiente ejemplo y obtendrás resultados correctos:

static void Main(string[] args) { Console.WriteLine("Starting Test"); var list = new List<int>(); // 1. Calculating inline without function call Stopwatch sw = Stopwatch.StartNew(); for (int d = 0; d < 100000000; d++) { int res = d * d; list.Add(res); } sw.Stop(); Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); // 2. Calulating power with function call list = new List<int>(); Stopwatch sw2 = Stopwatch.StartNew(); for (int d = 0; d < 100000000; d++) { int res = Power(d); list.Add(res); } sw2.Stop(); Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); Console.ReadKey(); }


Tu prueba está equivocada. En la segunda parte usas un int d lugar de un doble. Tal vez eso explica la diferencia horaria.