Mejorando el rendimiento de Ruby: reescribir C en Ruby
Comparación de rendimiento de Ruby
- En un repositorio reciente de comparación de lenguajes, Ruby resultó más rápido que R y Python, pero fue evaluado como el tercer lenguaje más lento.
- Los benchmarks se componen de dos pruebas, "Loops" y "Fibonacci", que destacan respectivamente los bucles y condicionales, la sobrecarga de llamadas a funciones y el rendimiento de la recursión.
Comparación de rendimiento entre Ruby y Node.js
- En una MacBook Pro con M3, Ruby 3.3.6 tarda 28 segundos en el ejemplo de bucles y 12 segundos en el ejemplo de Fibonacci.
- Node.js tarda alrededor de 1 segundo en ambos ejemplos.
- En una MacBook Air con M2, el rendimiento de Ruby es aún peor.
El significado de los benchmarks
- Puede que estos benchmarks no tengan realmente mucha importancia.
- Python fue evaluado como el lenguaje más lento, pero es el lenguaje más usado en GitHub.
- Un lenguaje de programación debe ser eficiente, pero su utilidad y productividad son más importantes que el rendimiento.
Aplicación de YJIT
- Al aplicar YJIT, el rendimiento de Fibonacci mejora considerablemente.
- En el ejemplo de bucles, la mejora de rendimiento es mínima.
Optimización del código Ruby
Range#each está escrito en C, por lo que YJIT no puede optimizarlo.
Integer#times fue convertido de C a Ruby en Ruby 3.3, lo que permite que YJIT lo optimice.
Array#each fue convertido de C a Ruby en Ruby 3.4.
Optimización de Integer#times
Integer#succ funciona más rápido que i += 1.
- YJIT optimiza
Integer#times y mejora significativamente el rendimiento.
Optimización de Array#each
Array#each fue convertido de C a Ruby en Ruby 3.4, por lo que YJIT puede optimizarlo.
- Se usa el módulo
Primitive para evaluar código C desde Ruby.
Repositorio Ruby Microbench
- Se ejecutan benchmarks usando distintas versiones de Ruby y YJIT.
- Ruby 3.4 con YJIT muestra una mejora significativa de rendimiento.
Optimización de range#each
- Se puede mejorar el rendimiento implementando la clase
Range en Ruby puro.
Biblioteca estándar de YJIT
- El equipo de YJIT está reemplazando código en C por Ruby para mejorar el rendimiento.
- Se usa el bloque
with_yjit para utilizar la implementación en Ruby cuando YJIT está activado.
Investigación sobre la optimización de YJIT
- YJIT optimiza el rendimiento convirtiendo bytecode de la VM de Ruby en código máquina.
- Se analiza el código máquina de
Integer#succ para entender el proceso de optimización de YJIT.
1 comentarios
Comentarios de Hacker News
El ejemplo del bucle repite mil millones de veces y usa bucles anidados. Se supone que este benchmark consumirá más del 99% del tiempo en las primeras dos líneas
uno se conoce en tiempo de compilación, el bucle interno puede reemplazarse por unas pocas instruccionesSe menciona futuras versiones de Ruby: Ruby 3.4.0 saldrá esta Navidad y Ruby 3.5.0 la próxima Navidad
Todavía queda cariño por Ruby. Gracias, Matz
Hubo un PR a inicios de 2024 para mejorar el rendimiento de
Integer#succ, y eso ayudó a entender por qué se usaInteger#succInteger#succse usa al reescribir métodos de bucle, y en el intérpreteopt_succ (i = i.succ)se procesa más rápido queputobject 1; opt_plus (i += 1)#succcon frecuencia por legibilidad, y lo uso dos veces en el método#bytesde una librería UUID para mantener el "modo de slicing de bits" al leer el códigoComparte una experiencia relacionada con TruffleRuby, diciendo que TruffleRuby es más rápido que Node.js y se acerca a Bun o Golang
Ruby se ha vuelto muy rápido, y TruffleRuby es aún más impresionante
No sabía que YJIT estaba escrito en Rust
Python fue el lenguaje más lento en el benchmark, pero a octubre de 2024 era el lenguaje más usado en Github
Hay un repositorio antiguo de comparación de lenguajes que incluye más lenguajes
Produjo un gran cambio en las soluciones de Advent of Code, y se ve sorprendentemente similar