tutorial rails instalar español ejemplos descargar ruby-on-rails debugging ruby-on-rails-3.2 rake asset-pipeline

ruby on rails - instalar - Cómo depurar una precompilación de activos de Rails que es insoportablemente lenta



ruby on rails windows 10 (3)

Estoy trabajando en un proyecto de Rails 3.2 y los activos han aumentado bastante en los últimos meses, aunque no consideraría que el proyecto sea grande. Los activos consisten en JS (sin coffee-script) y archivos SASS; tenemos bastantes imágenes pero han estado allí menos desde los primeros días, así que no creo que sean un factor importante. Podemos tener alrededor de una docena de libs y la mayoría son pequeñas, la más grande es Jquery UI JS. La implementación se realiza a través de Capistrano y comenzó a ser evidente que el despliegue en etapas fue significativamente más rápido que en la producción. Para ilustrar, evitando factores sobre diferentes servidores y efectos de red, simplemente ejecuté los siguientes tres comandos en secuencia en mi computadora portátil de la siguiente manera:

$ time RAILS_ENV=production bundle exec rake assets:precompile ^Crake aborted! [Note I aborted this run as I felt it was getting stupidly long...] real 52m33.656s user 50m48.993s sys 1m42.165s $ time RAILS_ENV=staging bundle exec rake assets:precompile real 0m41.685s user 0m38.808s sys 0m2.803s $ time RAILS_ENV=development bundle exec rake assets:precompile real 0m12.157s user 0m10.567s sys 0m1.531s

Así que me quedé rascándome la cabeza. ¿Por qué hay tales diferencias masivas entre los diversos ambientes? Puedo entender la brecha entre desarrollo y puesta en escena, pero nuestras configuraciones para puesta en escena y producción son idénticas . (Debo señalar que la compilación de producción se completará después de aproximadamente 2 horas).

Si bien el resultado final es que mi precompilación sea más rápida, quiero lograr esto al comprender a dónde va todo el tiempo y por qué existen grandes diferencias entre los entornos de Rails. He visto otras publicaciones sobre el uso de diferentes compresores y similares, pero no puedo encontrar ninguna información sobre cómo depurar estas tareas de rake para determinar dónde se está gastando el tiempo e identificar qué configuraciones pueden estar causando tales diferencias dramáticas.

No sé qué información adicional pueden necesitar las personas, por lo que se actualizará en caso de que los comentarios se hagan. TIA

Actualización: información adicional suministrada a continuación

config/environments/production.rb y config/environments/staging.rb (son exactamente lo mismo):

MyRailsApp::Application.configure do # Code is not reloaded between requests config.cache_classes = true # Full error reports are disabled and caching is turned on config.consider_all_requests_local = false config.action_controller.perform_caching = true # Disable Rails''s static asset server (Apache or nginx will already do this) config.serve_static_assets = true config.static_cache_control = "public, max-age=31536000" config.action_controller.asset_host = "//#{MyRailsApp::CONFIG[:cdn]}" # Compress JavaScripts and CSS config.assets.compress = true # Don''t fallback to assets pipeline if a precompiled asset is missed config.assets.compile = false # Generate digests for assets URLs config.assets.digest = true # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) config.i18n.fallbacks = true # Send deprecation notices to registered listeners config.active_support.deprecation = :notify end

La base config / application.rb es:

require File.expand_path(''../boot'', __FILE__) require ''rails/all'' if defined?(Bundler) # If you precompile assets before deploying to production, use this line Bundler.require(*Rails.groups(:assets => %w(development test))) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end module MyRailsApp CONFIG = YAML.load_file(File.join(File.dirname(__FILE__), ''config.yml''))[Rails.env] class Application < Rails::Application # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += %W(#{config.root}/app/workers) # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" # Configure sensitive parameters which will be filtered from the log file. config.filter_parameters += [:password] # Enable the asset pipeline config.assets.enabled = true # Stop precompile from looking for the database config.assets.initialize_on_precompile = false # Version of your assets, change this if you want to expire all your assets config.assets.version = ''1.0'' # Fix fonts in assets pipeline # http://stackoverflow.com/questions/6510006/add-a-new-asset-path-in-rails-3-1 config.assets.paths << Rails.root.join(''app'',''assets'',''fonts'') config.middleware.insert 0, ''Rack::Cache'', { :verbose => true, :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"), :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body") } # unless Rails.env.production? ## uncomment this ''unless'' in Rails 3.1, ## because it already inserts Rack::Cache in production config.middleware.insert_after ''Rack::Cache'', ''Dragonfly::Middleware'', :images config.action_mailer.default_url_options = { :host => CONFIG[:email][:host] } config.action_mailer.asset_host = ''http://'' + CONFIG[:email][:host] end end

Archivo de gemas:

source ''http://rubygems.org'' gem ''rails'', ''3.2.13'' gem ''mysql2'' gem ''dragonfly'', ''>= 0.9.14'' gem ''rack-cache'', :require => ''rack/cache'' gem ''will_paginate'' gem ''dynamic_form'' gem ''amazon_product'' # for looking up Amazon ASIN codes of books gem ''geoip'' gem ''mobile-fu'' gem ''airbrake'' gem ''newrelic_rpm'' gem ''bartt-ssl_requirement'', ''~>1.4.0'', :require => ''ssl_requirement'' gem ''dalli'' # memcache for api_cache gem ''api_cache'' gem ''daemons'' gem ''delayed_job_active_record'' gem ''attr_encrypted'' gem ''rest-client'' gem ''json'', ''>= 1.7.7'' gem ''carrierwave'' # simplify file uploads gem ''net-scp'' # Gems used only for assets and not required # in production environments by default. group :assets do gem ''therubyracer'' gem ''sass-rails'', ''~> 3.2.3'' gem ''compass'', ''~> 0.12.alpha'' gem ''uglifier'', ''>= 1.0.3'' gem ''jquery-fileupload-rails'' end gem ''jquery-rails'' gem ''api_bee'', :git => ''git://github.com/ismasan/ApiBee.git'', :ref => ''3cff959fea5963cf46b3d5730d68927cebcc59a8'' gem ''httparty'', ''>= 0.10.2'' gem ''twitter'' # Auth providers gem ''omniauth-facebook'' gem ''omniauth-twitter'' gem ''omniauth-google-oauth2'' gem ''omniauth-identity'' gem ''omniauth-readmill'' gem ''bcrypt-ruby'', "~> 3.0.0" # required for omniauth-identity gem ''mail_view'' # To use ActiveModel has_secure_password # gem ''bcrypt-ruby'', ''~> 3.0.0'' # Deploy with Capistrano group :development do gem ''capistrano'' gem ''capistrano-ext'' gem ''capistrano_colors'' gem ''rvm-capistrano'' # requirement for Hoof, Linux equivalent of Pow gem ''unicorn'' end group :test, :development do gem ''rspec-rails'' gem ''pry'' gem ''pry-rails'' end group :test do gem ''factory_girl_rails'' gem ''capybara'' gem ''cucumber-rails'' gem ''database_cleaner'' gem ''launchy'' gem ''ruby-debug19'' # Pretty printed test output gem ''shoulda-matchers'' gem ''simplecov'', :require => false gem ''email_spec'' gem ''show_me_the_cookies'' gem ''vcr'' gem ''webmock'', ''1.6'' end


Creo que necesita ver los parámetros de uso de la CPU en su servidor Prod.

Además, puede existir la posibilidad de que los activos se precompilan varias veces. Sugiero crear un directorio de activos en el directorio compartido creado por capistrano, copiar los cambios en el mismo y vincularlo a sus aplicaciones durante la implementación.

Heres cómo lo hago,

after "deploy:update_code" do run "export RAILS_ENV=production" run "ln -nfs #{shared_path}/public/assets #{release_path}/public/assets" # Also for logs and temp section. # run "ln -nfs #{shared_path}/log #{release_path}/log" # run "ln -nfs #{shared_path}/tmp #{release_path}/tmp" #sudo "chmod -R 0777 #{release_path}/tmp/" #sudo "chmod -R 0777 #{release_path}/log/" end


Es posible que esto no responda completamente a su pregunta, pero creo que es un comienzo lo suficientemente decente. Como verá, la respuesta precisa dependerá de la aplicación individual, las versiones de gemas, etc.

Asi que. Para el trabajo relacionado con activos, como usted sabe, Rails usa una biblioteca llamada Sprockets, que en las versiones más nuevas de Rails está, creo, enganchada en Rails como una Railtie. Inicializa un "entorno" de Sprockets que puede hacer cosas como mirar el manifiesto de su activo, cargar esos archivos, comprimirlos, darle nombres compilados a los activos compilados, etc.

De forma predeterminada, Sprockets::Environment registra su actividad en STDERR con un nivel de registro de FATAL , que no es muy útil en estas situaciones. Afortunadamente, Sprockets::Environment (a partir de 2.2.2 ) tiene un atributo de registro registrable que puede parchear a través de Rails, utilizando un inicializador.

Entonces, esto es lo que sugiero, para comenzar:

En config/initializers , crea un archivo, algo así como asset_logging.rb . En él, pon:

Rails.application.assets.logger = Logger.new($stdout)

Esto sobrescribe el registrador predeterminado con uno que escupirá más información a STDOUT . Una vez que tenga esta configuración, ejecute su tarea de precompilación de activos:

rake RAILS_ENV=production assets:precompile

Y debería ver resultados ligeramente más interesantes, como:

... Compiled jquery.ui.core.js (0ms) (pid 66524) Compiled jquery.ui.widget.js (0ms) (pid 66524) Compiled jquery.ui.accordion.js (10ms) (pid 66524) ...

Pero, al final, la respuesta final dependerá de:

  • qué "profundo" quieres ir con el registro de este material
  • qué versión específica de Rails, Sprockets, etc. está usando
  • y lo que encuentras en el camino

Como ya aprendió, el registro de spelunking en el nivel de tarea de Rake, o incluso en el nivel de Rails, no proporciona mucha información. E incluso hacer Piñones en sí mismo detallado (ver arriba) no te dice demasiado terriblemente.

Si quieres ir más allá de las Piñones, probablemente puedas parchear los diversos motores y procesadores que Sprockets encadenan obedientemente para hacer que la tubería de activos funcione. Por ejemplo, podría examinar las capacidades de registro de estos componentes:

  • Sass::Engine (convierte SASS a CSS)
  • Uglifier (envoltura del compresor JavaScript)
  • ExecJS (ejecuta JavaScript en Ruby, una dependencia de ambos Sprockets y Uglifier)
  • therubyracer (V8 incrustado en Ruby, utilizado por ExecJS )
  • etc.

Pero dejaré todo eso como "un ejercicio para el lector". ¡Si hay una bala de plata, ciertamente me gustaría saberlo!


hay muchas causas posibles para este problema.

para una posible causa, me gustaría saber cómo el tiempo de compilación de los activos aumentó en los diversos entornos para sus últimos despliegues. esto podría indicar si el problema es solo en los entornos o dentro de la compilación de activos en sí. podrías usar git bisect para eso. Por lo general, tengo implementadas mis aplicaciones para organizarlas a través de un jenkins u otro sistema ci, de modo que pueda ver las variaciones en el tiempo de implementación y cuándo fueron presentadas.

podría reducirse a un uso extensivo de los recursos CPU, MEMORIA (¿algún intercambio?), IO. Si compila los activos en los sistemas de producción, es posible que estén ocupados atendiendo su solicitud de aplicaciones. vaya a su sistema, haga una top de los recursos, tal vez haya demasiados archivos manejables al mismo tiempo ( lsof es bueno para eso).

Otra cosa podría ser que cargue o guarde algunos datos para su aplicación. las bases de datos suelen ser mucho más grandes en entornos de producción y producción y luego están en cajas de desarrollo. puedes poner algunas llamadas de Rails.logger en tus inicializadores o whaterver.