Los muchos intérpretes y tiempos de ejecución del lenguaje de programación Ruby

Publicado: 2022-03-11

Introducción

Así como hay muchos matices de la gema de rubí, existen múltiples implementaciones del intérprete de Rubí.

El intérprete de Ruby más utilizado es la implementación de referencia, Ruby MRI, desarrollada en C por el creador de Ruby (Yukihiro Matsumoto) y el equipo central de Ruby.

Nuestra Guía de contratación de Ruby on Rails menciona que algunos de los inconvenientes de Rails pueden resolverse o evitarse potencialmente mediante el uso de un intérprete alternativo de Ruby. Este artículo muestra las diversas implementaciones de intérpretes de Ruby existentes y los tiempos de ejecución disponibles en la actualidad, analizando las ventajas y desventajas de cada uno.

Una lista de intérpretes y tiempos de ejecución de Ruby, incluidos mruby, JRuby, RubyMotion, Rubinius y Ruby MRI

Historial de versiones de Ruby (y cómo afecta a las implementaciones alternativas)

Lamentablemente, no existe un equivalente de Python Language Reference para Ruby (ISO/IEC 30170:2012 describe Ruby 1.8 / Ruby 1.9, pero no existe una especificación correspondiente para Ruby 2.x). En ausencia de cualquier especificación de lenguaje de este tipo, los implementadores de Ruby generalmente confían en la RubySpec impulsada por la comunidad que especifica los comportamientos esperados del lenguaje Ruby a través de pruebas que se pueden ejecutar en cualquier intérprete de Ruby. Por lo tanto, los implementadores de Ruby utilizan RubySpec para verificar el cumplimiento del comportamiento de sus implementaciones de Ruby con el estándar de facto.

Debido a la falta de una especificación formal, los nuevos lanzamientos de Ruby a menudo simplemente corresponden a los nuevos lanzamientos de Ruby MRI. Vale la pena señalar que hay un problema abierto que analiza un proceso de diseño para desacoplar Ruby (el idioma) de Ruby MRI.

Sin embargo, dado el estrecho acoplamiento actual entre el lenguaje Ruby y la implementación de referencia de MRI, los desarrolladores de implementaciones alternativas de Ruby a veces tienen dificultades para mantenerse al día con los cambios de lenguaje introducidos en cada nueva versión de MRI.

Nunca fue tan difícil como en la transición entre Ruby 1.8 y Ruby 1.9. En 2007, en un esfuerzo por limpiar y consolidar la sintaxis de Ruby (ya que el lenguaje había evolucionado en la década desde el lanzamiento de Ruby 1.0), el equipo central de Ruby lanzó Ruby 1.9.0, una versión que introdujo muchas incompatibilidades anteriores en el lenguaje. . Como resultado, no todas las implementaciones de Ruby invirtieron el esfuerzo necesario para dar el salto sintáctico de 1.8 a 1.9. Como tal, hay varias implementaciones de Ruby basadas en 1.8 que la comunidad ya no usa, pero que aún puede encontrar en línea o hablar de ellas por manos antiguas de Ruby.

Cada Navidad se lanza una nueva versión de Ruby MRI, siguiendo un principio de control de versiones semántico. Ruby 2.0 (lanzado en 2013) y 2.1 (lanzado en 2014) introdujeron funciones de lenguaje adicionales que los desarrolladores de Ruby pueden aprovechar, sin perder la compatibilidad con versiones anteriores de Ruby 1.9.

¿Por qué usar una implementación alternativa de Ruby? ¿Qué tiene de malo la resonancia magnética?

Hay una variedad de implementaciones alternativas de Ruby, que admiten una amplia gama de casos de uso y entornos. Entornos Java Enterprise. Aplicaciones móviles. Implementaciones de JavaScript. Máquinas con poca CPU/RAM. Además de admitir estos casos de uso, las implementaciones alternativas a veces también pueden ofrecer un aumento adicional en la velocidad o una utilización de memoria más eficiente, según las características de su aplicación.

Durante mucho tiempo, muchos desarrolladores de Ruby on Rails utilizaron Ruby Enterprise Edition (REE) en lugar de MRI, aprovechando las mejores técnicas de administración de memoria en REE en comparación con la versión MRI en ese momento. (REE se suspendió posteriormente, aunque en 2012).

Si bien MRI es la implementación predeterminada de Ruby, no es necesariamente la opción correcta para todos los entornos y escenarios. Por ejemplo, el soporte de concurrencia de MRI es inferior al de JRuby o Rubinius. Además, aunque los esquemas de recolección de basura y memoria de MRI mejoran constantemente, todavía tienen algunos problemas.

El estudio de las implementaciones de Ruby que se presenta a continuación pretende ayudarlo a seleccionar el intérprete que mejor se adapte a las metas y restricciones operativas de su proyecto.

Intérprete Ruby de Matz (MRI) / CRuby

Escrito en C por el equipo central de Ruby dirigido por Yukihiro Matsumoto ("Matz", el creador de Ruby), MRI es la implementación de referencia de Ruby que sirve como estándar de facto. Si un proveedor de SO incluye una versión de Ruby como parte del software instalado del SO, por ejemplo, suele ser la versión MRI. MRI se beneficia de más miembros pagados del equipo central que cualquier otra implementación de Ruby, así como de recursos aportados dedicados por personas o empresas que desean mejorar el ecosistema de Ruby.

Cada Navidad se lanza una nueva versión de Ruby MRI, que a menudo implementa nuevas funciones de lenguaje, además de cambios estándar en la biblioteca. Las características se implementan primero en Ruby MRI, generalmente en base a discusiones en la lista de correo de desarrolladores principales de Ruby. Otras implementaciones de Ruby van a la zaga, en algunos casos incluso por años.

jruby

JRuby es una versión de Ruby implementada sobre Java Virtual Machine (JVM). A medida que se vuelve popular que los lenguajes más allá de Java se ejecuten sobre JVM (estoy mirando en su dirección, Clojure y Scala), es probable que una implementación de Ruby basada en JVM gane popularidad.

Ruby en la JVM también significa que Ruby puede ejecutarse en cualquier lugar donde se pueda ejecutar Java (como teléfonos Android, usando Ruboto, por ejemplo). Además, gracias a la interoperabilidad de JVM, el código JRuby puede utilizar la plataforma Java, incluidas las bibliotecas estándar y de terceros.

JRuby también es útil para llevar una solución basada en Rails a un entorno de implementación solo de Java, empaquetando la aplicación Rails como un archivo .war para implementar en un contenedor Tomcat, o como un subprograma Java que se ejecuta como parte de su interfaz web. , por ejemplo.

Sin embargo, para aquellos que no están acostumbrados a JVM, JRuby trae problemas estándar relacionados con JVM, como el inicio lento del intérprete de Ruby, la depuración de problemas de CLASSPATH si está utilizando bibliotecas de Java de terceros, mayor uso de memoria y el hecho de que ahora su código debe escribirse teniendo en cuenta las consideraciones de seguridad de subprocesos.

Además, algunas funciones de Ruby (las API de C y una de las poderosas herramientas de introspección de Ruby, el módulo ObjectSpace) no están implementadas en JRuby.

Dicho todo esto, las ventajas de usar JVM pueden superar las desventajas para ciertas situaciones o proyectos. La JVM permite muchas optimizaciones de rendimiento, como activar el compilador JIT o usar API y objetos nativos de Java.

Como ejemplo de un caso de uso convincente de JRuby, un antiguo compañero de trabajo tuvo una vez un problema de uso intensivo de la CPU que inicialmente resolvió con subprocesos en Ruby 1.9.3. Cuando cambió a JRuby y usó java.util.concurrent.Executors de Java, vio una mejora en el rendimiento de varios órdenes de magnitud (decenas de miles de veces más rápido) para esta operación. Mira su experimento aquí.

Rubinio

Rubinius es una implementación de Ruby que implementa un tiempo de ejecución genérico para lenguajes dinámicos sobre una máquina virtual de bajo nivel (LLVM). Con esta infraestructura y la tecnología de compilación JIT, Rubinius a menudo puede ejecutar código Ruby con menos gastos generales que MRI.

Rubinius también está construido usando tanto Ruby como sea posible para hacer que el desarrollo del intérprete/tiempo de ejecución sea más rápido y fácil.

Dato curioso: RubySpec surgió inicialmente en el proceso de implementación de Rubinius.

Al igual que JRuby, Rubinius incluye un compilador JIT, una mejor gestión de la memoria y una máquina virtual más madura que Ruby MRI. Sin embargo, a diferencia de JRuby, Rubinius admite bibliotecas de Ruby C y las bases de Rubinius están escritas en C++, no en Java.

Rubinius puede ser un buen término medio cuando necesita un alto rendimiento en sus servidores Rails sin la curva de aprendizaje u otras desventajas de JRuby.

rubí

mruby está diseñado para ser una versión integrable de Ruby (compatible con Ruby 1.9.3). Con mruby, puede ofrecer Ruby como un lenguaje de secuencias de comandos/automatización en aplicaciones nativas, usarlo para secuencias de comandos de juegos e incluso para programar placas de microcontroladores como Raspberry Pi.

Si su plataforma tiene severas limitaciones de recursos, mruby puede ser el intérprete de Ruby para usted. mruby también se utiliza para:

  • Cree aplicaciones para iOS (como competidor de RubyMotion, que se analiza a continuación)
  • Integre Ruby en las aplicaciones de iOS para acelerar el desarrollo
  • Ofrezca a los usuarios finales un lenguaje de secuencias de comandos integrado con fines de automatización

Con el Internet de las cosas convirtiéndose cada vez más en una realidad, la automatización del hogar cobrando fuerza y ​​las computadoras extremadamente portátiles (y relativamente poderosas) siendo cada vez más comunes, el panorama de las plataformas de destino para admitir es cada vez más diverso. mruby ayuda a que sea posible hacerlo con el mismo lenguaje productivo que se usaría en el escritorio.

Ópalo

Opal es un transpilador para convertir Ruby en JavaScript.

Con el auge de Coffeescript, los desarrolladores están aprendiendo que no tienen que escribir JavaScript para obtener JavaScript. Si bien Coffeescript ciertamente tiene sus ventajas, úselo el tiempo suficiente y seguramente se encontrará con cosas que no le gustan del idioma.

Ingrese Opal: escriba Ruby, obtenga Javascript . Muy genial.

Opal se esfuerza por ser lo más coherente posible con otras implementaciones de Ruby y, por lo tanto, también se prueba con un subconjunto de RubySpec. Sin embargo, existen algunas incompatibilidades derivadas de la naturaleza de JavaScript y los tiempos de ejecución de JavaScript. Por ejemplo, las cadenas y los símbolos en Opal son iguales, y Opal no proporciona ningún mecanismo de ejecución de subprocesos o shell.

Opal se ejecuta de forma independiente o se puede usar como parte de la canalización de activos de Rails (por ejemplo, para transpilar automáticamente su archivo somefile.js.rb a JavaScript).

Tal vez tenga un dominio problemático adecuado para el patrón de simultaneidad asincrónica de JavaScript (como un pequeño servicio de Node.js) pero desee el idioma o ciertas gemas del espacio de Ruby. Opal puede ser una buena solución para usted en ese caso.

O tal vez desee escribir una aplicación web completa de Ruby. Con Opal, puedes. Haga que un intérprete de Ruby ejecute su código Ruby del lado del servidor y luego haga que Opal genere JavaScript para ejecutarlo en el lado del cliente.

Opal reconoce que probablemente interactuará con otras API de JavaScript (DOM o Node.js, por ejemplo). Por lo tanto, facilita la transición a JavaScript y proporciona algo de azúcar sintáctico de Ruby sobre bibliotecas de JavaScript comunes como jQuery.

Sin embargo, la naturaleza centrada en JavaScript de Opal es tanto su fortaleza como su debilidad. La desventaja es que el tiempo de ejecución de Opal es el tiempo de ejecución de JavaScript, y Opal se basa en las decisiones de diseño de JavaScript. Entonces, si está buscando una buena implementación de Ruby para escribir un pequeño script de shell, o está buscando un mejor tiempo de ejecución de Ruby para su aplicación Rails, Opal probablemente no sea su mejor opción.

RubyMotion

RubyMotion es a la vez (a) una implementación de Ruby (escrita con Objective-C y Cocoa) y (b) un conjunto de enlaces de lenguaje para que los desarrolladores puedan acceder a las API de Cocoa a través de Ruby.

RubyMotion es un producto comercial que le permite escribir aplicaciones nativas de Cocoa en Ruby. RubyMotion 2.0 le permite escribir aplicaciones de iOS y Mac OS X en Ruby, y RubyMotion 3 promete brindar este mismo soporte a Android.

RubyMotion implementa la versión 1.9 del lenguaje Ruby.

Implementaciones difuntas

A lo largo de los años desde que se introdujo Ruby por primera vez, algunas de las implementaciones de Ruby que han surgido se han abandonado o descontinuado, como:

  • Edición Rubí Enterprise (REE). REE fue una bifurcación de MRI 1.8 de la gente de Phusion Passenger que implementó muchas mejoras de memoria y recolección de basura para desarrolladores web. Durante varios años, fue la implementación predeterminada de Ruby implementada para los sitios de producción de Rails. Sin embargo, nunca se actualizó para Ruby 1.9 o Ruby 2.0 y finalmente se suspendió en 2012.
  • IronRuby. IronRuby es Ruby implementado sobre Microsoft .NET, escrito en C#, y durante un tiempo el proyecto fue financiado por Microsoft. Abandonado en 2011, IronRuby admitió por última vez Ruby 1.8.6.

Envolver

Hay una amplia variedad de tiempos de ejecución e intérpretes para elegir en el entorno de Ruby. Para la mayoría de los proyectos de Ruby, la implementación de referencia de Ruby (Ruby MRI) sigue siendo el intérprete elegido. Sin embargo, las implementaciones alternativas de Ruby pueden ser la opción correcta para su proyecto, según sus objetivos y limitaciones funcionales y técnicas.

En su papel como la implementación de referencia de Ruby, MRI obtiene nuevas funciones de lenguaje más rápido, tiene historias de memoria y concurrencia lo suficientemente buenas (que solo están mejorando) y tiene la compatibilidad más amplia con gemas (algunas parcialmente escritas en C). En general, MRI es una opción sólida y confiable para el código Ruby de uso general.

Para implementaciones empresariales más grandes, o para situaciones en las que necesita interactuar con código Java (u otros lenguajes JVM) o necesita patrones de concurrencia altamente evolucionados, JRuby es una opción convincente.

Y, por supuesto, si tiene necesidades únicas (por ejemplo, escribir JavaScript, ejecutar en la generación actual de dispositivos integrados, etc.), las otras alternativas de Ruby pueden ser justo lo que está buscando.

Con una amplia variedad de tiempos de ejecución e intérpretes de Ruby para elegir, Ruby se muestra como un lenguaje flexible, útil para una amplia gama de entornos informáticos, que van desde una gran tienda corporativa de implementación de Java hasta software que controla ese semáforo en su oficina. conectaste tu Raspberry Pi el fin de semana pasado. Elegir la herramienta correcta para el propósito correcto es esencial, sí, pero espero que este artículo le haya mostrado que Ruby es mucho más que el intérprete de Ruby predeterminado que viene con su sistema operativo.

El mundo de Ruby se ve enormemente mejorado por los equipos de implementación alternativos de Ruby que trabajan con el equipo central de Ruby MRI a medida que se proponen cambios en el lenguaje. Agregan diversidad a la comunidad de implementación de Ruby, agregando sus experiencias de implementación de Ruby ganadas con tanto esfuerzo y sus propias perspectivas sobre las funciones que se incorporan al lenguaje. Los entusiastas de Ruby colectivamente tienen una gran deuda de gratitud con estos equipos. ¡Felicitaciones a ellos por sus esfuerzos!