Tradução: The Closet JRubyist | AkitaOnRails.com
The Closet JRubyist
Por muito tempo deixamos os contribuidores principais do JRuby serem as únicas vozes pelo JRuby. Eu sou um dos culpados de apenas usar, usar e usar o não apreciado trabalho da incansável equipe do JRuby. Charles, Ola, Tom, Nick, Vladimir e muitos outros precisam de agradecimentos.
Quase todos os projetos de JRuby que conheço não serão encontrados em blogs, twitter ou qualquer outro tipo de comunicação techno-coder favorito do mês. Esses projetos não vão se tornar populares ou terão os holofotes neles. A maioria dos trabalhos de JRuby é feito no vácuo interior de corporações burocratas. O trabalho em JRuby é escondido atrás de acordos de censura e mantidos secretos. As grandes histórias não foram contadas e Charles só pode dizer muito pouco porque não são projetos dele.
Esta é uma dessas histórias e espero que este post encoraje outros JRubistas a falar e pelo menos compartilhar partes de sua experiência com JRuby. Vocês devem isso à equipe JRuby e à comunidade Ruby em geral.
Vou começar sendo brusco e se quiser ignorar o resto do post por causa da próxima sentença então vá embora porque este post não é para você. JRuby é fantástico. O resto do post deve explicar porque essa afirmação é verdadeira.
Eu me juntei a um projeto que começou usando o MRI para embrulhar uma biblioteca C numa gem. A biblioteca C é um pacote de análise financeira usada para precificar instrumentos e extrair especificações de contratos. Trabalhar em C com o MRI foi fácil. Os métodos da API C do Ruby são simples e você quase se sente trabalhando em Ruby mesmo. Tudo estava bem como trabalhar em Ruby deve ser. Uma aplicação Rails foi construída para mostrar dados fornecidos pela gem. À medida que a comunidade Rails se movia em direção a novas estratégias de deployment nós também nos movíamos de webrick para mongrel para lighttpd, etc.
Então algumas das especificações de negócio requeriam que a precificação fosse feita em centenas de milhares de instrumentos de uma só vez. Uma mudança de uma ordem de magnitude em uso tornou a velocidade e consumo de memória algo importante. Precificar tantos instrumentos em 3 meses não ajuda. Isso precisava ser feito em paralelo.
Com isso minha equipe e eu criamos um sistema simples para distribuir dados e processá-los em paralelo usando Drb de maneira similar a Hadoop. Se estivéssemos usando JRuby na época Hadoop seria perfeito, mas o MRI não nos dava essa opção.
Bem nessa época, o MRI se tornou um grande gargalo. O MRI não aguentaria os cerca de 6 milhões de objetos que precisávamos empurrar pelo DRb e mesmo que pudesse enviar os dados aos workers no grid de máquinas ele não conseguiria usar todos os cores de cada máquina. Uma combinação de ficar sem memória e o MRI falhando em utilizar os núcleos de servidores de 64 cores levaram o projeto a uma parada.
JRuby 1.0 tinha acabado de ser lançado e estava começando a ganhar alguma tração. Um projeto 1.0? Certamente não conseguiria lidar com esses problemas. Mas sem nenhum outro lugar para ir pegamos a parte de API C de Ruby e movemos para C, JNI, Java e o JRuby. As novas ferramentas não eram tão agradáveis, mas se funcionasse, quem se importaria? Eu não. Eu gostava do trabalho poliglota de passar objetos Ruby em callbacks C e fazer testes unitários de C do JRuby. Coisas para esticar o cérebro.
Acabou que o JRuby não tinha problemas em gerenciar 8Gb de memória e 6 milhões de objetos sendo passados por DRb. Ter a JVM para gerenciar a memória com seus objetos Ruby não era tão ruim. Eu não precisava me importar mais com isso e não se importar com a JVM é anos luz à frente de ter que me importar com o gerenciamento de memória do MRI. Sim, existe valor real em usar a JVM.
Além disso, JRuby se encaixou no resto de nosso sistema MRI porque não estávamos tendo nenhum problema com o MRI conversando com o JRuby através de DRb. Eu tive uns pequenos problemas com IO e Socket, mas Charles e Ola estava disponíveis por IRC e os problemas foram resolvidos em questão de dias. A disponibilidade da equipe JRuby é algo que eu nunca encontrei em nenhuma comunidade. Charles sempre colocou minhas questões antes de suas tarefas e se você sabe alguma coisa sobre o homem, ele é ocupado. Eu não sei quantas palestras ele deu recentemente, mas suas mensagens do Twitter listam tantas cidades que eu não sei mais onde ele mora.
Os tempos iniciais de precificação ficaram em 1 hora e 15 minutos. Nada mal considerando que nosso cliente estava satisfeito com 2 dias.
Agora, a história poderia acabar aqui e eu poderia considerar a transição para JRuby um sucesso, mas a história continua.
Ajustar as opções da JVM nos permitiram mover o tempo para 45 minutos depois que mudamos para JRuby 1.1.1. Eu adicionei algumas das minhas descobertas para o wiki de ajustes de performance, que você pode encontrar aqui. Quando foi a última vez que você ouviu alguém passar opções ao garbage collector do MRI e ver melhorias de performance?
Exportar tantos dados acabou virando um problema também. O limite de 256 colunas do Excel não ficou feliz com meus arquivos com mais de 9 mil colunas e a gem padrão de planilhas do ruby teve problemas para lidar com mais de 7Mb. Felizmente, o projeto POI do Apache (Java) poderia lidar com esses problemas e ter mais funcionalidades como colunas auto-dimensionáveis e painéis congelados, que nenhuma outra gem compatível com MRI daria (sim, existem bindings de POI para Ruby). Nunca pensei que fosse gostar de trabalhar com as APIs de POI/Excel, mas JRuby mais as bibliotecas POI me deixaram sorrindo. Excel com um gosto de ruby é animal. Usar JRuby para embrulhar soluções Java pré-existentes é uma boa maneira para dormir à noite.
Em seguida mudamos nossas aplicações Rails para JRuby fazendo instalação como wars no JBoss. O problema de gerenciar mongrels foi embora e JBoss acabou sendo muito mais rápido dado que se dê memória suficiente para ele. Nick Sieger fez um grande trabalho com o warbler e o processo foi tranquilo. Infelizmente, com o número de aplicações que mudamos, os DBAs começaram a ficar irritados com os cerca de mais de 60 conexões usadas. Rails 2.2 não estava pronto ainda então pool de conexões dentro do Rails não era uma opção, mas usando JNDI dentro do JBoss funcionou perfeitamente. Usando ferramentas pré-existentes de Java com um adaptador escrito pela equipe do JRuby tornou meu trabalho mais fácil de novo.
Enquanto isso, o JRuby ainda estava lançando novas versões. Usar o 1.1.3 mudou nosso tempo de precificação para cerca de 15 minutos. Sim, de 1 hora e 15 minutos para apenas 15 minutos. Existiram alguns ajustes feitos pelo caminho, mas as melhorias mais significativas vieram do próprio JRuby. No seu estado atual a API C/Java/JRuby está exposto através de Merb (http/json), DRb (druby), Rails (http/xml, http/html) e um plugin de Excel e mais oportunidades à frente.
Fomos capazes de atualizar para uma nova versão de JRuby depois de um dia depois do lançamento. Sim, é assim estável e fácil de mudar. Sim, 1.1.5 está atualmente em nosso ambiente de produção. Atualizar para novas versões do MRI era normalmente um pesadelo para mim então eu acho a estabilidade bem vinda. O JRuby sendo um jar tem algumas vantagens maravilhosas.
Não vou entrar nos detalhes sobre outras bibliotecas que embrulhamos com JRuby, incluindo JFreeChart e QuicKFIX/J. Não vou entrar nos detalhes sobre usar JRuby com CORBA ou RMI e outras muitas ferramentas que se tornaram disponíveis pelo uso do JRuby.
Atualmente, o MRI não está nem mesmo instalado em nossos servidores de produção e não vejo ele sendo instalado no futuro. A maioria se não todas as maneiras dos dados estarem disponíveis ou usáveis é devido ao JRuby. O JRuby tornou meu trabalho muito mais fácil e tornou muitas funcionalidades que implementei possíveis. Tente.