30.2. ¿Cuándo usar JIT? #

La compilación JIT es beneficiosa principalmente para consultas de larga duración limitadas por la CPU (CPU-bound). Frecuentemente, estas serán consultas analíticas. Para consultas cortas, la sobrecarga adicional de realizar la compilación JIT a menudo será mayor que el tiempo que puede ahorrar.

Para determinar si se debe utilizar la compilación JIT, se utiliza el costo total estimado de una consulta (ver la Chapter 69 y la Section 19.7.2). El costo estimado de la consulta se comparará con la configuración de la jit_above_cost. Si el costo es mayor, se realizará la compilación JIT. Luego se necesitan tomar dos decisiones adicionales. En primer lugar, si el costo estimado es mayor que la configuración de la jit_inline_above_cost, se integrarán en línea las funciones cortas y los operadores utilizados en la consulta. En segundo lugar, si el costo estimado es mayor que la configuración de la jit_optimize_above_cost, se aplicarán optimizaciones costosas para mejorar el código generado. Cada de estas opciones aumenta la sobrecarga de la compilación JIT, pero puede reducir considerablemente el tiempo de ejecución de la consulta.

Estas decisiones basadas en el costo se tomarán en el momento de la planificación, no en el de la ejecución. Esto significa que cuando se usan sentencias preparadas y se utiliza un plan genérico (ver la PREPARE), los valores de los parámetros de configuración vigentes en el momento de la preparación controlan las decisiones, no las configuraciones en el momento de la ejecución.

Note

Si la jit está configurada en off, o si no hay ninguna implementación de JIT disponible (por ejemplo, porque el servidor se compiló sin --with-llvm), no se realizará JIT, incluso si fuera beneficioso según los criterios anteriores. Configurar jit en off tiene efectos tanto en el momento de la planificación como en el de la ejecución.

Se puede utilizar EXPLAIN para ver si se usa JIT o no. Como ejemplo, aquí hay una consulta que no está usando JIT:

=# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class;
                                                 QUERY PLAN
-------------------------------------------------------------------​------------------------------------------
  Aggregate  (cost=16.27..16.29 rows=1 width=8) (actual time=0.303..0.303 rows=1.00 loops=1)
    Buffers: shared hit=14
    ->  Seq Scan on pg_class  (cost=0.00..15.42 rows=342 width=4) (actual time=0.017..0.111 rows=356.00 loops=1)
          Buffers: shared hit=14
  Planning Time: 0.116 ms
  Execution Time: 0.365 ms

Dado el costo del plan, es completamente razonable que no se haya utilizado JIT; el costo de JIT habría sido mayor que los ahorros potenciales. Ajustar los límites de costo conducirá al uso de JIT:

=# SET jit_above_cost = 10;
SET
=# EXPLAIN ANALYZE SELECT SUM(relpages) FROM pg_class;
                                                 QUERY PLAN
-------------------------------------------------------------------​------------------------------------------
  Aggregate  (cost=16.27..16.29 rows=1 width=8) (actual time=6.049..6.049 rows=1.00 loops=1)
    Buffers: shared hit=14
    ->  Seq Scan on pg_class  (cost=0.00..15.42 rows=342 width=4) (actual time=0.019..0.052 rows=356.00 loops=1)
          Buffers: shared hit=14
  Planning Time: 0.133 ms
  JIT:
    Functions: 3
    Options: Inlining false, Optimization false, Expressions true, Deforming true
    Timing: Generation 1.259 ms (Deform 0.000 ms), Inlining 0.000 ms, Optimization 0.797 ms, Emission 5.048 ms, Total 7.104 ms
  Execution Time: 7.416 ms

Como se puede ver aquí, se utilizó JIT, pero no la integración en línea ni la optimización costosa. Si también se redujeran la jit_inline_above_cost o la jit_optimize_above_cost, eso cambiaría.