2012-04-20 30 views
18

Tengo una aplicación de Rails 3.2.2 que estoy buscando ejecutar usando JRuby 1.6.7 (modo 1.9.2).JRuby Performance

Tengo una aplicación de ejemplo que se ejecuta en la RM rubí 1.9.3 y una petición típica está volviendo en ~ 40 ms: Completado 200 OK en 36ms (Visitas: 27.5ms | ActiveRecord: 8.2ms)

Bajo JRuby usando la misma solicitud es entre 3 y 20 veces más lenta dependiendo de la página. Para la misma operación anterior, toma ~ 180ms: Completó 200 OK en 180ms (Vistas: 153.0ms | ActiveRecord: 24.0ms)

¿Es esta una diferencia de rendimiento normal? He leído que JRuby es más o menos igual en velocidad con MRI. Los resultados son válidos para mi Mac y un servidor de Windows (donde desafortunadamente tendrá que ejecutarse). Empacarlo con Warbler bajo Tomcat es igual de lento.

Los tiempos anteriores corresponden a una aplicación básica de rieles creada para probar JRuby. En la aplicación más compleja, los tiempos están aún más separados. En esa aplicación, se está ejecutando más código ruby ​​en algunas páginas. Parece que cuanto más depende la página de Ruby, mayor es la diferencia de rendimiento que estoy observando. No he afinado JRuby, ya que no sé exactamente por dónde empezar.

Así que mis preguntas son: ¿es esto normal? ¿Qué puedo hacer para sintonizar JRuby?

Respuesta

18
Is this a normal performance difference? 
I have read that JRuby is roughly equal on speed with MRI. 

No, eso no es normal. Una vez que la JVM se ha calentado, las solicitudes de Rails bajo JRuby suelen ser significativamente más efectivas que bajo MRI, tanto en términos de velocidad de ejecución sin procesar como de recolección de basura.

Parece que su aplicación está mal configurada. Lo primero que debe verificar es la configuración de los Rails en sí; asegúrese de que Rails no esté en modo de desarrollo y que config.threadsafe! esté habilitado en su entorno de producción. El modo Threadsafe dará como resultado que haya una sola copia compartida de los Rails cargados en la memoria cuando se esté ejecutando su aplicación.

También compruebe que la configuración de su base de datos se está aprovechando de la agrupación de conexiones, p. pool: 20 en database.yml.

Finalmente, verifique sus configuraciones JVM y JRuby - ambas son altamente ajustables. Debe asegurarse de que haya suficiente memoria asignada a la JVM durante el inicio, y luego suficiente memoria para un funcionamiento normal y sin problemas de su aplicación; de lo contrario, la JVM se verá obligada a acumular basura constantemente de forma prematura y con frecuencia, lo que degradará significativamente el rendimiento.

Por ejemplo algunos de los ajustes para un VPS modestamente specced podría ser algo como:

-Xmx500m -Xss1024k -Djruby.memory.max=500m -Djruby.stack.max=1024k

... pero no copiar estos ajustes a ciegas! Deberá experimentar y determinar qué es bueno para usted con respecto a los recursos de memoria que están disponibles en su servidor.

Dicho esto, aunque JRuby probablemente consuma menos memoria que la suma total de múltiples procesos de Rails bajo MRI, definitivamente tendrá que asignar un poco más por adelantado para un único proceso de JVM.Sea generoso con JRuby y JRuby se le recompensa por su amabilidad :-)

Puede leer más acerca de cómo ajustar JRuby y la JVM aquí: https://github.com/jruby/jruby/wiki/PerformanceTuning

actualización

No es necesario para establecer config.threadsafe! en Rails 4.0 y superior; es threadsafe por defecto.

+0

Al funcionar en el modo 'producción', en comparación con el modo de desarrollo, a veces ofrece una respuesta 5-6 veces más rápida. Al menos eso fue en mi caso. Gracias por notar eso. – Aleks

3

¡Actualice a jruby 1.6.8 o jruby 1.7.x con JAVA 7!

Rendimiento increíble.

Tuvimos el mismo problema y es tremendamente rápido ahora (con solo cambiar las versiones).

+2

Tengo las mismas malas actuaciones. Intentó java 7 y Jruby 1.7, una nueva aplicación de rieles es más lenta que un fuerte proyecto actual con MRI. Ergio. – m4tm4t

4

Estoy viendo el mismo comportamiento, pero tenga en cuenta que JRuby necesita mucho más tiempo para calentarse. En realidad, soy un poco optimista de que JRuby finalmente se pondrá al día.

Es posible acelerar este 'calentamiento' configurando algunas opciones. El Ruby - compilador> código de bytes de Java se puede enseñar a JIT compila todos los métodos en la primera invocación estableciendo la siguiente env var:

export JRUBY_OPTS="-J-Djruby.jit.threshold=1 -J-Djruby.jit.max=16384"

Para mí, después de actualizar una página Rieles un par de veces, sigue siendo 2 -3 veces más lento que el MRI Ruby, pero al menos 3 veces más rápido que antes.

También tenga en cuenta que el tiempo de ejecución de java es JIT compilando el bytecode java al código máquina de manera similar, pero este JIT no entrará en funcionamiento hasta que se invoque un método 10.000x cuando se utilice el tiempo de ejecución del servidor. Esto puede ser configured as well.

export JRUBY_OPTS="-J-Djruby.jit.threshold=10 -J-Djruby.jit.max=16384 -J-XX:CompileThreshold=10" -J-XX:ReservedCodeCacheSize=128M"

Con estas opciones, JRuby on Rails da casi el mismo rendimiento o mejor que la RMN.

Tenga en cuenta que estas opciones son solo para una evaluación comparativa impaciente. En realidad, casi siempre es una mala idea ejecutar la compilación de JIT de forma tan agresiva; Está perdiendo un tiempo y una memoria valiosos en la compilación JIT del código que solo podría ejecutarse varias veces. Sin embargo, muestra cómo el rendimiento final de JRuby podría ser mejor de lo que esperaba en función de las ejecuciones iniciales.

Dejarme saber si esto funciona para usted.