Mi conjetura es que las sugerencias de predicción en el nivel de instrucción de la máquina son, en el mejor de los casos, un ruido y, en el peor de los casos, un detrimento (bytes de instrucciones desperdiciados) en la arquitectura moderna fuera de orden y de ejecución especulativa. Hacerlo sería como decirle a la CPU que no haga nada, que deje de hacer sus cosas ya inteligentes para las que está diseñada.
En segundo lugar, el grado en que se puede mejorar la predicción de la rama depende de la causa de la predicción errónea y de la facilidad con la que se pueden medir los efectos de rendimiento u observar la tendencia de la rama.
Sin embargo, creo que la bolsa existente de trucos de optimización JIT ya puede mejorar la predicción de rama en cierta medida, incluso sin la ayuda de contadores de predicción de rama de CPU.
Solo un ejemplo de código muy simple:
public void repeatHistory(int value)
{
if (value == 1492)
{
landing();
}
else if (value == 1776)
{
ratifying();
}
}
Supongo que repeatHistory
se llama muchas veces. Cuando el monitor de rendimiento basado en muestreo analiza las estadísticas de la pila de llamadas, puede encontrar que, por cualquier razón, las repeatHistory()
llamadas se ratifying()
producen con más frecuencia que las llamadas anteriores landing()
. Según esta observación, el próximo paso de la generación de código JIT para el repeatHistory
método tendrá esto en cuenta y realizará una o más optimizaciones:
- Mueva el cheque por
(value == 1776)
delante del cheque por(value == 1492)
- Intente incorporar el
ratifying()
método en la rama enrepeatHistory()
- Si
repeatHistory()
se llama desde otro bucle, intente desenrollar el bucle o inserte el repeatHistory()
método en ese bucle.
- Y muchos otros.
Después de aplicar una optimización, a menudo es necesario analizar nuevamente para ver si se pueden aplicar más optimizaciones, porque una exitosa a menudo abrirá la puerta a más oportunidades.