Os muitos intérpretes e tempos de execução da linguagem de programação Ruby
Publicados: 2022-03-11Introdução
Assim como existem muitos tons da gema ruby, existem várias implementações do interpretador Ruby.
O interpretador Ruby mais comumente usado é a implementação de referência, Ruby MRI, desenvolvida em C pelo criador do Ruby (Yukihiro Matsumoto) e pela equipe principal do Ruby.
Nosso Guia de Contratação de Ruby on Rails menciona que algumas das desvantagens no Rails podem ser resolvidas ou evitadas usando um interpretador Ruby alternativo. Este artigo mostra as várias implementações e runtimes existentes de intérpretes Ruby disponíveis hoje, discutindo as vantagens e desvantagens de cada uma.
Ruby Version History (e como isso afeta implementações alternativas)
Infelizmente, não há equivalente do Python Language Reference para Ruby (ISO/IEC 30170:2012 descreve Ruby 1.8 / Ruby 1.9, mas não existe especificação correspondente para Ruby 2.x). Na ausência de qualquer especificação de linguagem, os implementadores de Ruby normalmente confiam no RubySpec orientado pela comunidade que especifica os comportamentos esperados da linguagem Ruby por meio de testes que podem ser executados em qualquer interpretador Ruby. RubySpec é, portanto, usado por implementadores Ruby para verificar a conformidade comportamental de suas implementações Ruby com o padrão de fato.
Devido à falta de uma especificação formal, novos lançamentos do Ruby geralmente correspondem simplesmente aos novos lançamentos do Ruby MRI. Vale a pena notar que há uma questão em aberto que discute um processo de design para desacoplar Ruby (a linguagem) do Ruby MRI.
Dado o forte acoplamento atual, no entanto, entre a linguagem Ruby e a implementação de referência de MRI, os desenvolvedores de implementações alternativas de Ruby às vezes lutam para acompanhar as mudanças de linguagem introduzidas em cada nova versão de MRI.
Nunca foi tão difícil quanto na transição entre Ruby 1.8 e Ruby 1.9. Em 2007, em um esforço para limpar e consolidar a sintaxe do Ruby (já que a linguagem evoluiu na década desde o lançamento do Ruby 1.0), a equipe principal do Ruby lançou o Ruby 1.9.0, uma versão que introduziu muitas incompatibilidades com versões anteriores na linguagem . Como resultado, nem todas as implementações de Ruby investiram o esforço necessário para fazer o salto sintático de 1.8 para 1.9. Como tal, existem várias implementações de Ruby baseadas em 1.8 que não são mais usadas pela comunidade, mas que você ainda pode encontrar online ou comentadas por mãos antigas de Ruby.
Uma nova versão do Ruby MRI é lançada todo Natal, seguindo um princípio de versionamento semântico. Ruby 2.0 (lançado em 2013) e 2.1 (lançado em 2014) cada um introduziu recursos de linguagem adicionais que os desenvolvedores de Ruby podem aproveitar, sem perder a compatibilidade com versões anteriores do Ruby 1.9.
Por que usar uma implementação alternativa do Ruby? O que há de errado com a ressonância magnética?
Há uma variedade de implementações alternativas de Ruby, suportando uma grande variedade de casos de uso e ambientes. Ambientes Java Enterprise. Aplicações Móveis. Implementações de JavaScript. Máquinas com CPU/RAM baixa. Além de oferecer suporte a esses casos de uso, às vezes, implementações alternativas também podem oferecer um aumento extra na velocidade ou utilização de memória mais eficiente, dependendo das características do seu aplicativo.
Por muito tempo, muitos desenvolvedores Ruby on Rails usaram Ruby Enterprise Edition (REE) em vez de MRI, aproveitando as melhores técnicas de gerenciamento de memória no REE em comparação com a versão MRI da época. (REE foi posteriormente descontinuado embora em 2012.)
Embora MRI seja a implementação padrão do Ruby, não é necessariamente a escolha correta para todos os ambientes e cenários. Por exemplo, o suporte de simultaneidade do MRI é inferior ao do JRuby ou Rubinius. Além disso, embora os esquemas de memória e coleta de lixo da MRI estejam melhorando constantemente, eles ainda apresentam alguns problemas.
A pesquisa de implementações Ruby que se segue destina-se a ajudá-lo a selecionar o intérprete mais adequado aos objetivos e restrições operacionais do seu projeto.
Matz's Ruby Interpreter (MRI) / CRuby
Escrito em C pela equipe principal do Ruby liderada por Yukihiro Matsumoto (“Matz”, o criador do Ruby), MRI é a implementação de referência do Ruby que serve como o padrão de fato. Se um fornecedor de sistema operacional inclui uma versão do Ruby como parte do software instalado do sistema operacional, por exemplo, geralmente é a versão MRI. A MRI se beneficia de mais membros pagos da equipe principal do que qualquer outra implementação Ruby, bem como recursos dedicados de pessoas ou empresas que desejam melhorar o ecossistema Ruby.
Uma nova versão do Ruby MRI – muitas vezes implementando novos recursos de linguagem, além de mudanças na biblioteca padrão – é lançada todo Natal. Os recursos são implementados primeiro no Ruby MRI, geralmente com base em discussões na lista de discussão do desenvolvedor principal do Ruby. Outras implementações de Ruby ficam para trás, em alguns casos até por anos.
JRuby
JRuby é uma versão do Ruby implementada sobre a Java Virtual Machine (JVM). À medida que se torna popular para linguagens além do Java serem executadas em cima da JVM (estou olhando em sua direção, Clojure e Scala), uma implementação de Ruby baseada em JVM provavelmente ganhará popularidade.
Ruby na JVM também significa que Ruby pode ser executado em qualquer lugar que Java possa ser executado (como telefones Android, usando Ruboto, por exemplo). Além disso, graças à interoperabilidade da JVM, o código JRuby pode fazer uso da plataforma Java, incluindo bibliotecas padrão e de terceiros.
JRuby também é útil para trazer uma solução baseada em Rails em um ambiente de implementação somente Java, empacotando o aplicativo Rails como um arquivo .war
para implementar em um contêiner Tomcat, ou como um applet Java rodando como parte de seu front-end web , por exemplo.
Para aqueles que não estão acostumados com a JVM, JRuby traz problemas relacionados à JVM padrão, como inicialização lenta do interpretador Ruby, problemas de depuração de CLASSPATH se você estiver usando bibliotecas Java de terceiros, maior uso de memória e o fato de que agora seu código precisa ser escrito com considerações de segurança de thread em mente.
Além disso, alguns recursos do Ruby (APIs C e uma das poderosas ferramentas de introspecção do Ruby, o módulo ObjectSpace) não são implementados no JRuby.
Dito isso, as vantagens de usar a JVM podem superar as desvantagens para determinadas situações ou projetos. A JVM permite muitas otimizações de desempenho, como ativar o compilador JIT ou usar objetos e APIs Java nativos.
Como exemplo de um caso de uso convincente do JRuby, um ex-colega de trabalho meu uma vez teve um problema de uso intensivo de CPU que ele resolveu inicialmente com threads no Ruby 1.9.3. Quando ele mudou para JRuby e usou java.util.concurrent.Executors
do Java, ele viu uma melhoria de desempenho de várias ordens de magnitude (dezenas de milhares de vezes mais rápido) para esta operação. Veja o experimento dele aqui.
Rubinius
Rubinius é uma implementação de Ruby que implementa um runtime genérico para linguagens dinâmicas em cima de uma máquina virtual de baixo nível (LLVM). Usando essa infraestrutura e tecnologia de compilador JIT, o Rubinius pode executar código Ruby com menos sobrecarga do que MRI.

O Rubinius também é construído usando o máximo possível de Ruby para tornar o desenvolvimento do interpretador/tempo de execução mais rápido e fácil.
Curiosidade: RubySpec surgiu inicialmente no processo de implementação do Rubinius.
Assim como o JRuby, o Rubinius inclui um compilador JIT, melhor gerenciamento de memória e uma máquina virtual mais madura que o Ruby MRI. No entanto, ao contrário do JRuby, o Rubinius suporta bibliotecas Ruby C e os fundamentos do Rubinius são escritos em C++, não em Java.
Rubinius pode ser um bom meio termo quando você precisa de alto desempenho em seus servidores Rails sem a curva de aprendizado ou outras desvantagens do JRuby.
sujo
mruby foi projetado para ser uma versão incorporável do Ruby (suportando Ruby 1.9.3). Com o mruby, você pode oferecer Ruby como linguagem de script/automação em aplicativos nativos, usá-lo para scripts de jogos e até mesmo para programar placas de microcontroladores como o Raspberry Pi.
Se sua plataforma tem restrições severas de recursos, o mruby pode ser apenas o interpretador Ruby para você. mruby também está sendo usado para:
- Crie aplicativos iOS (como concorrente do RubyMotion, discutido abaixo)
- Incorpore Ruby em aplicativos iOS, para velocidade de desenvolvimento
- Ofereça aos usuários finais uma linguagem de script incorporada para fins de automação
Com a Internet das Coisas se tornando cada vez mais uma realidade, a automação residencial ganhando espaço e os computadores extremamente portáteis (e relativamente poderosos) sendo mais comuns, o cenário de plataformas de destino para suporte está se tornando cada vez mais diversificado. mruby ajuda a tornar isso possível com a mesma linguagem produtiva que se usaria na área de trabalho.
Opala
Opal é um transpilador para transformar Ruby em JavaScript.
Com a ascensão do Coffeescript, os desenvolvedores estão aprendendo que não precisam digitar JavaScript para obter JavaScript. Embora o Coffeescript tenha reconhecidamente suas vantagens, use-o por tempo suficiente e você certamente encontrará coisas que não gosta na linguagem.
Digite Opal: Digite Ruby, obtenha Javascript . Muito legal.
O Opal se esforça para ser o mais consistente possível com outras implementações de Ruby e, portanto, também é testado em um subconjunto de RubySpec. Algumas incompatibilidades existem, no entanto, decorrentes da natureza dos tempos de execução JavaScript e JavaScript. Por exemplo, strings e símbolos no Opal são iguais, e o Opal não fornece nenhum mecanismo de execução de encadeamento ou shell.
O Opal é executado de forma independente ou pode ser usado como parte do pipeline de ativos do Rails (por exemplo, para transpilar automaticamente seu arquivo somefile.js.rb
em JavaScript).
Talvez você tenha um domínio de problema adequado para o padrão de simultaneidade assíncrona do JavaScript (como um pequeno serviço Node.js), mas queira a linguagem ou certas gems do espaço Ruby. O Opal pode ser uma boa solução para você nesse caso.
Ou talvez você queira escrever um aplicativo web Ruby full stack. Com o Opala, você pode. Tenha um interpretador Ruby executando seu código Ruby do lado do servidor e, em seguida, tenha o Opal gerando JavaScript para executar no lado do cliente.
A Opal reconhece que você provavelmente estará interagindo com outras APIs JavaScript (o DOM ou Node.js, por exemplo). Portanto, facilita a transição para JavaScript e fornece um pouco de açúcar sintático Ruby sobre bibliotecas JavaScript comuns, como jQuery.
A natureza centrada em JavaScript do Opal, no entanto, é tanto sua força quanto sua fraqueza. No lado negativo, o tempo de execução do Opal é o tempo de execução do JavaScript, e o Opal é informado pelas decisões de design do JavaScript. Então, se você está procurando por uma boa implementação de Ruby para escrever um pequeno shell script, ou procurando um tempo de execução Ruby melhor para seu aplicativo Rails, o Opal provavelmente não é sua melhor escolha.
RubyMotion
RubyMotion é (a) uma implementação Ruby (escrita usando Objective-C e Cocoa) e (b) um conjunto de ligações de linguagem para que os desenvolvedores possam acessar APIs Cocoa por meio de Ruby.
RubyMotion é um produto comercial que permite escrever aplicativos nativos Cocoa em Ruby. RubyMotion 2.0 permite escrever aplicativos iOS e Mac OS X em Ruby, e RubyMotion 3 promete trazer esse mesmo suporte para Android.
RubyMotion implementa a versão 1.9 da linguagem Ruby.
Implementações Extintas
Ao longo dos anos, desde que o Ruby foi introduzido pela primeira vez, algumas das implementações do Ruby que surgiram foram abandonadas ou descontinuadas, como:
- Ruby Enterprise Edition (REE). O REE foi um fork do MRI 1.8 do pessoal da Phusion Passenger que implementou muitas melhorias de memória e coleta de lixo para desenvolvedores web. Por vários anos, foi a implementação padrão do Ruby implantada para sites Rails de produção. Ele nunca foi atualizado para Ruby 1.9 ou Ruby 2.0, porém, e foi descontinuado em 2012.
- FerroRubi. IronRuby é Ruby implementado em cima do Microsoft .NET, escrito em C#, e por um tempo o projeto foi financiado pela Microsoft. Abandonado em 2011, o IronRuby deu suporte ao Ruby 1.8.6 pela última vez.
Embrulhar
Há uma grande variedade de runtimes e intérpretes para escolher no cenário Ruby. Para a maioria dos projetos Ruby, a implementação de referência Ruby (Ruby MRI) continua sendo o interpretador de escolha. No entanto, implementações alternativas de Ruby podem muito bem ser a escolha certa para seu projeto, dependendo de suas metas e restrições funcionais e técnicas.
Em seu papel de implementação de referência do Ruby, o MRI obtém novos recursos de linguagem mais rapidamente, tem simultaneidade e histórias de memória suficientemente boas (que estão cada vez melhores) e tem a maior compatibilidade com gems (algumas parcialmente escritas em C). Em suma, MRI é uma escolha sólida e confiável para código Ruby de uso geral.
Para implementações corporativas maiores ou para situações em que você precisa interagir com código Java (ou outras linguagens JVM) ou precisa de padrões de simultaneidade altamente evoluídos, o JRuby é uma opção atraente.
E, claro, se você tiver necessidades únicas (por exemplo, escrever JavaScript, rodar na geração atual de dispositivos embarcados e assim por diante), as outras alternativas Ruby podem ser exatamente o que você está procurando.
Com uma ampla variedade de runtimes e interpretadores de Ruby para escolher, Ruby se mostra uma linguagem flexível, útil para uma ampla gama de ambientes de computação, desde uma grande loja de implantação de Java corporativo até software que controla o semáforo em seu escritório você conectou seu Raspberry Pi no último fim de semana. Escolher a ferramenta certa para o propósito certo é essencial, sim, mas espero que este artigo tenha mostrado a você que Ruby é muito mais do que o interpretador Ruby padrão que veio com seu sistema operacional.
O mundo do Ruby é bastante aprimorado por equipes alternativas de implementação do Ruby trabalhando com a equipe principal do Ruby MRI à medida que as alterações na linguagem são propostas. Eles adicionam diversidade à comunidade de implementação do Ruby, adicionando suas experiências de implementação do Ruby conquistadas com muito esforço e suas próprias perspectivas sobre os recursos que vão para a linguagem. Os entusiastas do Ruby coletivamente devem a essas equipes uma grande dívida de gratidão. Parabéns a eles por seus esforços!