How to profile Rake task? - rake

I need to profile the rake task. Cause I'm noob I know only how to profile .rb code
like this: ruby -Ilib -S ruby-prof -p graph_html profile.rb > profile.html
But how do I profile a specific Rake task?

Rake is just a Ruby script, so you should be able to just call ruby-prof against rake, in the same way you'd profile any other script.
Given your invocation of ruby-prof, try:
ruby -Ilib -S ruby-prof -p graph_html `which rake` TASK > profile.html
I've just used the following command line:
ruby-prof -p graph_html /usr/local/bin/rake19 import_from_aws file=~/sourcedata batch=test1 > /tmp/profile.html
To profile an invocation of:
rake19 import_from_aws file=~/sourcedata batch=test1

If you want 'coarse' profiling and want to find out which task is the bottleneck, I suggest Mike William's excellent piece of code from here. It worked beautifully when I was profiling my Rake tasks.
module Rake
class Task
def execute_with_timestamps(*args)
start = Time.now
execute_without_timestamps(*args)
execution_time_in_seconds = Time.now - start
printf("** %s took %.1f seconds\n", name, execution_time_in_seconds)
end
alias :execute_without_timestamps :execute
alias :execute :execute_with_timestamps
end
end

I think it's worth mentioning that you might want to profile it using bundle instead of rake directly if you happen to be using bundler.
ruby-prof -p graph_html `which bundle` -- 'exec' 'rake' '-T' > profile.html

Related

Capistrano 3: How can I suppress status output?

I've created a Capistrano task to execute a rake command. I plan to redirect the output (STDOUT) to a file. E.g.
cap production invoke:rake TASK=mytask > out
This works, but my output includes some additional Capistrano status output, e.g.
00:00 invoke:rake
01 $HOME/.rbenv/bin/rbenv exec bundle exec rake mytask
...
✔ 01 ubuntu#mydomain.com 11.399s
Is there any way to suppress this?
It's probably stderr output. If so, you can redirect standard error to standard out like so:
cap production invoke:rake TASK=mytask > out 2>&1
Okay, so I think I figured out a pretty good solution.
The key was to use capture (not documented in Capistrano 3.x, but still works).
https://github.com/capistrano/capistrano-2.x-docs/blob/master/2.x-DSL-Action-Inspection-Capture.md
namespace :invoke do
desc "Execute a rake task on a remote server"
task :rake do
if ENV['TASK']
on roles(:app) do
with rails_env: fetch(:rails_env) do
puts capture :rake, ENV['TASK']
end
end
else
puts "\n\nFailed! You need to specify the 'TASK' parameter!",
"Usage: cap <stage> invoke:rake TASK=your:task"
end
end
end

Run Play application in production mode using dist taks

I am using 'dist' task to generate a distribution of my play application. But if I unzip the generated artifact, in the bin/ directory I have access to the bash file generated by the 'dist' task. The last line of the script is : run "$#"
I saw in the official Play Framework documentation that 'run' command should not be used in production mode, and the recommended way is to generated a distribution with task 'dist'
Why 'dist' is generating a bash script which is using 'run' commmand if it is not recommended in production mode?
I am asking this, because when I deploy my application in production, the first request is slow...it seems the development behavior. But I am using the 'dist' command.
I would appreciate any help.
Thank you.
You are mixing two different things.
The run command stated in the Play documentation is a SBT command, that will start your app in dev mode. So to use that command you have to use activator or sbt (ex: ./activator run).
The run you see in that script is a bash function (defined a little above), that will start your app in production mode. A little snippet from that function:
# Actually runs the script.
run() {
# TODO - check for sane environment
# process the combined args, then reset "$#" to the residuals
# (...)
execRunner "$java_cmd" \
${java_opts[#]} \
"${java_args[#]}" \
-cp "$(fix_classpath "$app_classpath")" \
"${mainclass[#]}" \
"${app_commands[#]}" \
"${residual_args[#]}"
(...)
}
So, if you use this script to run your app, it will start in production mode.

Can I pass a multiline argument to rake task? (Not using ENV vars)

Both
rake some:task["aaa
bbb
ccc"]
and
rake some:task["aaa\nbbb\nccc"]
fail.
Dose Rake accept multiline arguments in the first place?
Do it like this :
require 'rake'
task :taskname, [:argument1, :argument2] do |t, args|
puts "Args are: #{args}"
end
In command line:
> rake taskname[1,2]
Args are: {:argument1=>"1", :argument2=>"2"}
I looked up the code and found that it's impossible to send multi "line" params to rake command.
https://github.com/ruby/rake/blob/86af0ef6d793b85068a44fb3407b23c9c9b09bc7/lib/rake/application.rb#L154
/^some_patterns$/ =~ string.to_s
It looks like a rake command is supposed to be a single line.

How to get the final command to be executed by sshkit

I want to create a gem that has de ability to take a task and wrap all commands in another command.
For example, the capistrano3-unicorn gem unicorn:start task will execute on the server something like bundle exec unicorn -c unicorn.rb -E production, but the execute method is wrapped by a within method, so the command to be executed on the server will be something like cd /home/deploy/application/myapp/current && bundle exec unicorn -c unicorn.rb -E production
I want to be able to create a rake task that takes that unicorn:start task and wrap it inside another task.
For example if I want to create an upstart config file for the app, I could adds this command to a upstart.conf template and the run service my-unicorn-app start
That would be a use case I'm trying to pursue.
In SSHKit formatters the write command is called with a command arg that have what I'm looking for. But I need this at capistrano task level.
Thanks
I think what you're asking is how to access the exact command that is sent via SSH. What you're looking for is the #command method, on the return value of which you can call #to_command. Since #command is a private method, we need to use #send.
namespace :unicorn
task :set_restart_command do
on(roles(:web)) do
within release_path do
set(:unicorn_start_command,
send(:command, :unicorn, "-c unicorn.rb -E production").to_command)
end
end
end
end
Now, in another task, you can use fetch(:unicorn_start_command)

Run a perl script at startup in Ubuntu

I have a perl script that I need to run once at startup with an argument under my user account.
So when I boot the system up it needs to execute a command like this,
./path/to/script.pl start
Any ideas?
You could use a line in your crontab (crontab -e)
To run a command at startup:
edit /etc/crontab
Add the following line:
#reboot root perl ./path/to/script.pl start
^^^ Runs as root. Change "root" to "BlackCow" to run as BlackCow
Or, you could use upstart (add a .conf file to /etc/init/). Here's a copy and paste from my notes:
Use upstart to run a daemon at reboot/start
e.g. /etc/init/prestocab.conf:
#!upstart
description "node.js server"
author "BlackCow"
start on (local-filesystems and net-device-up IFACE=eth0)
stop on shutdown
script
export HOME="/root"
exec sudo -u root /usr/local/bin/node /home/prestocab/prestocab.com/www/socket.io/server.js 2>&1 >> /var/log/prestocab.log
end script
To use:
start prestocab
stop prestocab
restart prestocab
#
You might want to use some sort of process monitor to restart the daemon if it crashes
Depends on what init you are using, if your version of Ubuntu is using upstart
you have to configure the appropriate Upstart start scripts, if not
the rc scripts based on your runlevel. Check update-rc.d.
On Ubuntu, the simplest way is to add this line to your /etc/rc.local file (before the exit 0 line, substituting username with your own user name):
su -c "./path/to/script.pl start" username &