Profile Guided Optimizations, o simplemente PGO, es una técnica que permite a los compiladores recopilar información extra acerca de la ejecución de un programa, de manera que puedan refinar el código generado en base a esos datos.

Aunque parece algo muy lógico, no fue hasta el Intel C++ en su versión 6, creo, que no empezó a estar disponible para PC, sus resultados, sin ser dramáticos, si que mejoraban levemente la calidad del código generado.

Hoy día, las cosas han cambiado sustancialmente, así, una de las causas del aumento de velocidad en Firefox 3, y Opera 9.5 entre otros, cuando los comparamos con sus antecesores, es precisamente el uso de PGO, que logra aumentar el rendimiento de partes críticas de los programas entre el 1% y el 50%.

La metodología es bien sencilla, primeramente se compila nuestro programa con una herramienta que soporte PGO, como GCC o Visual C++, generando automáticamente un ejecutable con código extra de monitorización.

Ese programa monitorizado, se ejecuta, y se le hace realizar las tareas típicas o críticas del mismo. Al terminar, tenemos disponible la información de intrumentación, que utilizará el compilador en una segunda pasada para optimizar el código en base a ella.

De esta forma, el compilador es capaz de detectar circunstancias, que una compilación estática no permite contemplar, o bien solo puede hacerlo de una forma muy costosa.

Estas optimizaciones, son por un lado refinamientos de optimizaciones ya disponible, como las funciones intrínsecas, las funciones inline, el uso de registros de CPU, o bien la vectorización de código que permite paralelizar tareas, pero con una información adicional que les permite ser más eficientes.

Por otro lado, abre la puerta a nuevas optimizaciones, como podría ser la optimización de bloques de código, esto es, colocar más cerca en memoria fragmentos de código que dependen unos de otros, para que idealmente quepan en la misma página, y viceversa, es decir, mover el código que se usa con menos frecuencia, o no se usa en absoluto, a otras páginas de memoria, de manera que el más común obtenga posiciones ventajosas, o la más interesante optimización de saltos condicionales.

Hace años, la mayoría de procesadores, añadieron un subsistema nuevo a su circuitería, se trataba de la unidad predictora de saltos. Esta unidad, se encargaba de predecir si el salto iba a efectuarse o no, y en su caso, ir avanzando en lo posible la ejecución de la instrucción a la que saltar, con el fin de aumentar el rendimiento. Su buen funcionamiento, mejoraba el desempeño en tanto la unidad predictora de saltos, pudiera determinar si el salto condicional iba a efectuarse o no. En caso de error de predicción, el trabajo avanzado no servía de nada, así que debía ser descartado, y aplicado de nuevo en base al nuevo destino. En equipos actuales, basicamente el sistema predictor de saltos, utiliza una estrategia global, con estadísticas con información anterior, para determinar la probabilidad del salto. Estos sistemas, tipicamente tienen un ratio de acierto superior al 90%, pero el 10% restante se equivocan, por lo que la información que agrega PGO, puede ser de gran utilidad.