practicas - reglas de nombrado de variables en c#
Método de evaluación comparativa de llamadas en C# (6)
Esta pregunta ya tiene una respuesta aquí:
Estoy buscando una manera de comparar las llamadas de método en C #.
He codificado una estructura de datos para la asignación universitaria, y solo se me ocurrió una forma de optimizar un poco, pero de una manera que agregaría un poco de sobrecarga en todas las situaciones, al mismo tiempo que convertía una llamada O (n) en O (1) en algunos.
Ahora quiero ejecutar ambas versiones con los datos de prueba para ver si vale la pena implementar la optimización. Sé que en Ruby, podría ajustar el código en un bloque de Benchmark y hacer que produzca el tiempo necesario para ejecutar el bloque en la consola. ¿Hay algo como eso disponible para C #?
Aquí hay algunas cosas que he encontrado por prueba y errores.
- Deseche el primer lote de (miles) iteraciones. Lo más probable es que sean afectados por el JITter.
- La ejecución del punto de referencia en un objeto
Thread
separado puede dar resultados mejores y más estables. No se por que - He visto a algunas personas usar
Thread.Sleep
por cualquier motivo antes de ejecutar el punto de referencia. Esto solo empeorará las cosas. No se por que Posiblemente debido al JITter. - Nunca ejecute el punto de referencia con la depuración habilitada. El código probablemente ejecutará órdenes de magnitud más lentas.
- Compila tu aplicación con todas las optimizaciones habilitadas. Algunos códigos pueden verse afectados drásticamente por la optimización, mientras que otros no lo serán, por lo que la compilación sin optimización afectará la confiabilidad de su índice de referencia.
- Al compilar con las optimizaciones habilitadas, a veces es necesario evaluar de alguna manera la salida del punto de referencia (por ejemplo, imprimir un valor, etc.). De lo contrario, el compilador puede "descifrar" que algunos cálculos son inútiles y simplemente no los realizarán.
- La invocación de delegados puede tener una sobrecarga notable al realizar ciertos puntos de referencia. Es mejor poner más de una iteración dentro del delegado, de modo que la sobrecarga tenga poco efecto en el resultado del índice de referencia.
- Los perfiladores pueden tener sus propios gastos generales. Son buenos para decirle qué partes de su código son cuellos de botella, pero no son realmente buenos para evaluar de manera confiable dos cosas diferentes.
- En general, las soluciones de evaluación comparativa de lujo pueden tener una sobrecarga notable. Por ejemplo, si desea comparar muchos objetos utilizando una interfaz, puede ser tentador envolver cada objeto en una clase. Sin embargo, recuerde que el constructor de la clase también tiene gastos generales que deben tenerse en cuenta. Es mejor mantener todo lo más simple y directo posible.
Los perfiladores ofrecen los mejores puntos de referencia ya que diagnostican todo su código, sin embargo, lo ralentizan mucho. Los perfiladores se utilizan para encontrar cuellos de botella.
Para optimizar un algoritmo, cuando sepa dónde están los cuellos de botella, use un diccionario de nombre -> cronómetro, para realizar un seguimiento de las secciones críticas de rendimiento durante el tiempo de ejecución.
Parece que quieres un profiler . Recomiendo encarecidamente el perfilador EQATEC , ya que es el mejor que he probado. Lo bueno de este método sobre un simple cronómetro es que también proporciona un desglose del rendimiento sobre ciertos métodos / bloques.
Podría usar la clase Cronómetro incorporada para "Proporciona un conjunto de métodos y propiedades que puede usar para medir con precisión el tiempo transcurrido". Si buscas una forma manual de hacerlo. Aunque no estoy seguro de automatizado.
Robé la mayor parte de lo siguiente del método de Jon Skeet para la evaluación comparativa:
private static void Benchmark(Action act, int interval)
{
GC.Collect();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < interval; i++)
{
act.Invoke();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
Robado (y modificado) de la respuesta de Yuriy:
private static void Benchmark(Action act, int iterations)
{
GC.Collect();
act.Invoke(); // run once outside of loop to avoid initialization costs
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
act.Invoke();
}
sw.Stop();
Console.WriteLine((sw.ElapsedMilliseconds / iterations).ToString());
}
A menudo, un método particular tiene que inicializar algunas cosas, y no siempre desea incluir esos costos de inicialización en su índice de referencia general. Además, desea dividir el tiempo total de ejecución por el número de iteraciones, de modo que su estimación sea más o menos independiente del número de iteraciones.