Pregunta

Hola,

Recientemente hemos actualizado una aplicación a Rails 3.0.4 (3.0.5 en el servidor Devel en línea). La mayoría de los cambios de 2.3.10 a 3.0.4 se debieron a complementos y gemas obsoletos o obsoletos, y se solucionaban con relativa facilidad. Pero una cosa me hace enojar:

Cada solicitud web, en modo de desarrollo, hace que el proceso del servidor asigne alrededor de 50-60 MB más memoria que antes. Este recuerdo es no liberado después de la solicitud, al menos no todo. Después de 10-20 solicitudes, cada instancia de Ruby se consumió 500 MB de RAM, mientras que nuestros rieles anteriores 2.3.10 instancias rara vez fueron superiores a 200 MB.

Esto hace que sea imposible ejecutar nuestras 1300 pruebas, porque los 4 GB de RAM de la máquina Devel se llenan antes del final de las pruebas. Solo sucede en modo de desarrollo con cache_classes = false. Si cambio cache_classes a verdadero, las instancias de Rails consumirán aproximadamente 200 MB de memoria y luego me quedan allí. Sin embargo, durante las pruebas, incluso con cache_classes = true, el uso de la memoria crecerá.

Consulté ObjectSpace y descubrí que con cada solicitud, alrededor de 3500 nuevos Proc, hasta 50 '000 nuevas cuerdas y 3000 hash y matrices nuevas se crean y no se liberan. Estas cadenas (cuando se abandonaron) contenían todo mi código fuente, incluidos complementos y gemas, documentación, comentarios del código fuente y nombres de rutas. (¿Por qué?)

Para encontrar la causa de esto, esto es lo que probé: (después de cada cambio, golpeé las aplicaciones con ab -n 50.)

  1. Creé un Aplicación Fresh Rails 3 con un solo recurso y controlador y sqlite3 db. El uso de la memoria comenzó a 60 MB y se mantuvo por debajo de 80 MB.
  2. Cambié 'sqlite3' a 'pg' y apuntó la nueva aplicación Rails 3 a mi Postgres DB existente. El uso de la memoria comenzó a 110 MB y no creció más allá de 130 MB. (Pregunta secundaria: ¿Por qué la gema de Postgres usa mucha más memoria que la gema SQLITE3?)
  3. Copié sobre mi Gemfile y Gemfile.lock Desde la aplicación Broken Rails3 hasta la aplicación Bare Bones y corrió instalación de paquete. Ningún cambio, la memoria se mantuvo en aproximadamente 115 MB, sin importar cuántas solicitudes se hicieron.
  4. Creé un "def foocontroller vacío; def foo; render: text => 'foo' end; final" en la aplicación rieles roto3. El uso de la memoria creció más lentamente, pero aún nunca dejó de crecer después de las solicitudes.
  5. Eliminé cada ruta, excepto la ruta Foocontroller. Ningún cambio.
  6. Deshabilité todas las gemas excepto las siguientes: pg, rails, aasm, will_paginate, geokit-rails3, koala, omniauth, paperclip. Ningún cambio.
  7. Deshabilité todos los antes de las personas antes y después de la aplicación en ApplicationController y todos los no esenciales include en el medio ambiente. RB. También sincronicé Boot.RB, Environment.RB y Application.RB con mi aplicación Bare-Bones Rails 3, excepto por cinco observadores relativamente simples, archivos de autoinforme en /lib y filter_parameters. Ningún cambio. Cada nueva solicitud todavía consumía 10-50 MB adicionales de RAM.

Si tiene una idea de lo que va mal aquí, y dónde podría estar la filtración de memoria, realmente agradecería cualquier ayuda. Estoy corriendo Rails 3.0.4 en OS X Snow Leopard, Rails 3.0.5 en Debian Lenny y

¡Gracias!

Acercándose:

He eliminado todos los complementos, cada gema, cada extensión y todo lo que no escribí personalmente, para que mi aplicación esté básicamente desnuda. Especialmente, eliminé estos complementos: acts_as_list, acts_as_tree, asset_packager, forgot_password, fudge_form, fudge_scaffold, paperclippolymorph, query_trace, rails_upgrade, repeated_auto_complete-0.1.0, role_requirement, to_select, validates_url, and ym4r_gm.

Ahora mi aplicación, ¡solo el Foocontroller anterior todavía funciona! - Comienza con 65 MB y nunca va más allá de 75 MB de RAM, incluso después de martillarlo con ab -n 1000 -c1 (1000 solicitudes HTTP a /foo usando ApacheBench). Desafortunadamente, sin los complementos, este es también el único URI que funciona.

Después de cavar un poco, parece que una combinación entre la autenticación RESTful y actúa como complementos de Máquina de Estado (AASM) provoca la fuga de memoria. Ver también https://github.com/satish/restful-authentication/issues#issue/11. Todavía no estoy seguro de por qué, y solo hacer "incluir AASM" en mi proyecto básico no causa el crecimiento del uso de RAM solo por sí mismo.

Investigaré más.

Culpable encontrado

Es Aasm. En Rails 3 parece filtrarse aasm :: xxx instancias de objeto. ver

Segundo culpable encontrado

Hubo otra fuga de memoria en RSPEC. Esto hizo que mis pruebas sean casi insoportablemente lentas, incluso después de eliminar el AASM, porque dos tareas de RSPEC de ejecución paralela (usando https://github.com/grosser/parallel_tests) Tomó casi 3GB de memoria al final. Ver https://github.com/rspec/rspec-core/issues/#issue/321.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top