Capistrano is dead - use Mina
Up until lately I was happy using Capistrano for my deployments. But then I noticed the following:
Capistrano was utilizing 70 % of a physical CPU core when deploying on the go.
I'm on a dual core system so this impacts my Mac Book Pros overall performance, battery life and it kept me waiting for a long long time. My iPhone was at edge speed so I figured Capistrano spent most of the time waiting for network I\O - busy waiting that is.
So I profiled Capistrano using perftools.rb. Capistrano spent about 50% on Compat.io_select over each deployment run. That's 50 % of a total of 40 seconds it took to deploy & restart my application server. The percentage spent waiting on Compact.io_select decreases to about 10% as the network speed increases to regular DSL levels.
The interesting part is that this is just CPU time. When profiling wall time Compact.io_select is at 9%, while Object#process_iteration is at 84%. Object#process_iteration is a wrapper Capistrano introduces around Kernel#select which 'should' not do busy waiting. But Capistrano kept my CPU busy anyways.
I converted my Capistrano configuration to Mina to see if it was any better.
Contrary to Capistrano Mina creates a Bash script based on your deployment configuration and executes the script on the server side using a single SSH connection. In theory this should be way faster than Capistrano which creates multiple SSH connections. It should have a far smaller CPU footprint as well given that Ruby is only used to assemble a Bash script.
Timing both setups led to the following results:
$ time mina deploy
real 0m23.999s
user 0m0.188s
sys 0m0.054s
$ time cap deploy
real 0m40.561s
user 0m0.897s
sys 0m0.191s
As you can see Mina deployments take about half the time it takes Capistrano to deploy and it didn't use much CPU.
For comparison only, here's a stripped-down version of my Capistrano configuration
require "rvm/capistrano"
require 'bundler/capistrano'
set :application, "my-app"
namespace :deploy do
task :start, :roles => :app, :except => { :no_release => true } do
run "sudo supervisorctl start #{application}:*"
end
task :stop, :roles => :app, :except => { :no_release => true } do
run "sudo supervisorctl stop #{application}:*"
end
task :restart, :roles => :app, :except => { :no_release => true } do
run "sudo supervisorctl restart #{application}:*"
end
end
as well as Minas:
require 'mina/bundler'
require 'mina/rails'
require 'mina/git'
task :rvm do
queue "PATH=$PATH:$HOME/.rvm/bin"
queue "source $HOME/.rvm/scripts/rvm"
queue "#{deploy_to}/.rvm/bin/rvm rvmrc load"
end
desc "Deploys the current version to the server."
task :deploy do
invoke :rvm
deploy do
invoke :'git:clone'
invoke :'bundle:install'
to :launch do
queue 'sudo supervisorctl restart my-app:*'
end
end
end
Conclusion
Mina is faster than capistrano, uses less CPU and less network bandwidth. Since it generates a bash script for deployment it's also much more transparent what's going on and how to change it to act the way you want it to. Verdict:
Use Mina already!



