Compilando código JIT en 5μs
La compilación JIT para bases de datos se está reconsiderando con enfoques ultrarrápidos de “copy-and-patch” que pueden generar código máquina en microsegundos, evitando la gran latencia de LLVM y aun así logrando mejoras notables sobre la interpretación. Los comentaristas sopesan estas mejoras de rendimiento frente a las preocupaciones de seguridad al relajar políticas estrictas de W^X, la complejidad y la superficie de ataque de los JIT (especialmente para entradas no confiables) y los ámbitos limitados en los que un JIT compensa el coste añadido de portabilidad y mantenimiento. Varios señalan marcos JIT más ligeros, técnicas de JIT manual en lenguajes como Common Lisp e incluso la generación de código asistida por LLM como formas de hacer más prácticos los JIT especializados.
Seguridad de JIT y W^X
- Una parte sostiene que JIT es intrínsecamente menos seguro porque requiere memoria escribible y ejecutable, socavando políticas estrictas de W^X y habilitando exploits más potentes.
- Otros responden que los JIT modernos normalmente asignan páginas RW, escriben el código y luego las cambian a RX, de modo que W^X se preserva por mapeo.
- Hay debate sobre si esto tiene “implicaciones a nivel de sistema” o si es solo una decisión de endurecimiento por proceso; algunos dicen que el sistema operativo ya debe gestionar esos permisos, otros subrayan que permitir ejecución de código dinámico aumenta el impacto de los errores.
- Se citan ejemplos de plataformas que restringen fuertemente JIT (iOS, GrapheneOS) y de técnicas como la verificación de bytecode y el etiquetado de memoria por hardware para hacer JIT más seguro.
- Varios comentarios señalan que los JIT aumentan la superficie de ataque del proceso anfitrión (especialmente al ejecutar entradas no confiables, como navegadores o consultas a bases de datos), pero no otorgan nuevas capacidades más allá de las que el proceso ya tiene.
- Se invocan ROP y técnicas similares para argumentar que, si un proceso puede ejecutar cualquier código, la ejecución arbitraria de código es efectivamente posible con o sin JIT.
Diseño de JIT, rendimiento y LLVM frente a enfoques ligeros
- Varios comentarios enfatizan que los JIT basados en LLVM tienen alta latencia y pueden ser inapropiados para cargas de trabajo que necesitan compilación muy rápida (p. ej., consultas de Postgres).
- Los enfoques de JIT ligeros —plantillas copy-and-patch, pequeñas bibliotecas (p. ej., SLJIT, GNU Lightning, AsmJit) o backends personalizados— sacrifican menos optimizaciones a cambio de un tiempo de compilación mucho menor.
- Los benchmarks discutidos en las publicaciones enlazadas muestran que los JIT simples pueden lograr mejoras de velocidad significativas frente a la interpretación con un tiempo de compilación despreciable, mientras que LLVM puede pasar decenas de milisegundos compilando.
- Los comentarios centrados en bases de datos subrayan que la optimización del plan de consulta (p. ej., el orden de los joins) importa mucho más que el JIT; la granularidad actual de JIT de Postgres (por expresión, no por pipeline) se ve como una limitación fundamental.
¿La generación de código basada en plantillas es “JIT real”?
- Algunos descartan el enfoque como “solo plantillas de ensamblador”, pero otros replican que:
- Los compiladores no optimizadores siguen siendo compiladores.
- Copy-and-patch es una técnica JIT estándar y legítima.
- Se dan ejemplos de generadores de código muy simples (sin asignación de registros, con mucho uso de pila) que solo son unas pocas veces más lentos que binarios muy optimizados -O3, pero mucho más rápidos que los intérpretes.
Common Lisp y JIT manual
- Se discuten implementaciones de Common Lisp como un punto intermedio:
- Algunas compilan todo de forma anticipada; otras admiten bytecode más compilación nativa opcional.
evaly la compilación al cargar se presentan como una forma de JIT.- Hay conmutadores para alternar entre intérprete y compilador en el uso de REPL, sacrificando tiempo de compilación a favor de velocidad de ejecución.
- Se elogia un estilo de “JIT manual” —elegir explícitamente qué compilar para mejorar el rendimiento— como un compromiso práctico y más simple.
El papel de la IA en escribir JITs y sistemas complejos
- Las opiniones divergen mucho:
- Algunos dicen que los modelos actuales producen código pobre en dominios complejos, útil sobre todo para boilerplate, CRUD, conexión de APIs y detección simple de errores.
- Otros informan grandes ganancias de productividad usando IA para esbozar componentes complejos (incluidos JITs), convirtiendo una semana de trabajo en horas, siempre que un ingeniero competente descomponga las tareas y revise la salida.
- Hay debate sobre:
- Cuánta experiencia de dominio sigue siendo necesaria (muchos dicen “mucha”).
- Si la calidad del código generado por IA es objetivamente mala o solo estilísticamente distinta.
- El riesgo de que usuarios sin experiencia publiquen código escrito por IA que parece decente superficialmente pero es frágil.
Otras aplicaciones y observaciones
- Algunos comentaristas sugieren usar ideas similares de JIT basadas en plantillas para cortafuegos y generación dinámica de eBPF.
- Se mencionan los motores de regex, los sistemas históricos de BASIC y Lisp, y los DBMS modernos como dominios clásicos o naturales para JIT.
- El hilo también toca brevemente intérpretes verificados formalmente y binarios estáticos firmados como una alternativa de seguridad extrema frente a JIT y código nativo.