Considere el siguiente código:
public class Playground { private static final int MAX = 100_000_000; public static void main(String... args) { execute(() -> {}); execute(() -> {}); execute(() -> {}); execute(() -> {}); } public static void execute(Runnable task) { Stopwatch stopwatch = Stopwatch.createStarted(); for (int i = 0; i < MAX; i++) { task.run(); } System.out.println(stopwatch); } }
Esto actualmente imprime lo siguiente en mi Intel MBP en Temurin 17:
3.675 ms 1.948 ms 216.9 ms 243.3 ms
Observe la ralentización de 100* para la tercera (y cualquier subsiguiente) ejecución. Ahora, obviamente, esta NO es la forma de escribir puntos de referencia en Java . El código de bucle no hace nada, por lo que espero que se elimine para todas y cada una de las repeticiones. Además, no pude repetir este efecto usando JMH, lo que me dice que la razón es delicada y frágil.
¿Entonces, por qué pasa ésto? ¿Por qué de repente habría una desaceleración tan catastrófica? ¿Qué está pasando debajo del capó? Una suposición es que C2 nos abandona, pero ¿con qué limitación nos estamos topando?
Cosas que no cambian el comportamiento:
Cosas que "arreglan" el comportamiento. En realidad, la tercera invocación y todas las subsiguientes parecen ser mucho más rápidas, lo que sugiere que la compilación eliminó correctamente los bucles por completo:
task.run()
lambdas dentro del ciclo,execute()
, aún manteniendo 4 lambdas diferentes.