capistrano / rails

Official Ruby on Rails specific tasks for Capistrano
http://www.capistranorb.com/
MIT License
867 stars 270 forks source link

Feature request: Be able to change assets:precompile CPU priority #258

Closed eoinkelly closed 1 year ago

eoinkelly commented 2 years ago

We sometimes hit an issue where the Webpack compile part of the assets:precompile takes enough CPU that it causes response times to go up noticeably.

I created a workaround by running assets:precompile under a lower CPU priority using nice. I chose nice because

  1. It is always available on Linux/unix AFAIK
  2. It correctly changes the priority of and child processes spawned by assets:precompile (unlike things like cpulimit)
  3. It is a lot less faff to implement than cgroups etc.

I'm guessing I'm not the only person who has hit this issue so I think it could potentially be useful to have this as an (opt-in, turned on via config) part of this gem.

I am happy to work up a PR if this is something the core team would consider.

# config/deploy.rb

###
# The capistrano-rails gem provides a `deploy:assets:precompile` task. We
# override that task here because we want to run `bundle exec rails assets:precompile`
# with a lower CPU priority than other processes on the system so that it
# doesn't take CPU away from the running puma processes.
#
# We use the unix `nice` command to achieve this ("man nice" for help). Nice's
# process priorities range from -19 (highest priority) to +20 (lowest priority).
# Processes on Ubuntu have a "nice value" of 0 by default so we choose a
# priority of "3" which is slightly lower than other processes.
#
Rake::Task["deploy:assets:precompile"].clear_actions
namespace :deploy do
  namespace :assets do
    task :precompile do
      on release_roles(fetch(:assets_roles)) do
        within release_path do
          with rails_env: fetch(:rails_env), rails_groups: fetch(:rails_assets_groups) do
            execute "nice", "-n", "3", "bundle", "exec", "rails", "assets:precompile"
          end
        end
      end
    end
  end
end
eoinkelly commented 1 year ago

An update on this after living with it for a while:

This technically works every time but it's not always effective. We have still noticed some issues serving traffic on small (t3.medium) EC2 instances while Webpack is compiling.

We have been successful using cpulimit rather than nice but we had to compile it ourselves from https://github.com/opsengine/cpulimit to get the version which also limits child processes. That approach is much too niche and the original approach isn't effective so I'm closing this. :shrug: