显示总体运行时间,以秒计时。 User Time : 程序自身消耗时间 System Time : 系统调用时间 Real Time : 总时间 CPU Time : 大于(fork)或者小于(wait) Real Time
TIMEFORMAT=$'real\t%E\tuser\t%U\tsys\t%S\tcpu\t%P'
# For Bash, Doesn't work with ZSH
跟踪系统调用和信号
strace -e trace=read,write -o /tmp/strace_io.log $CMD
cat /tmp/strace_io.log | grep read | \
awk 'BEGIN {FS="="}{ sum += $2} END {print sum}'
分析Bundler的依赖关系
gperftools for ruby code * gproftools : Fast, multi-threaded malloc() and nifty performance analysis tools
strace -e trace=read,write -o /tmp/strace_io.log $CMD
cat /tmp/strace_io.log | grep read | \
awk 'BEGIN {FS="="}{ sum += $2} END {print sum}'
gem 'perftools.rb', require: 'perftools'
CPUPROFILE=/tmp/prof CPUPROFILE_REALTIME=1 time rspec
pprof.rb --text /tmp/prof
DEMO
题外话 GC
{
RUBY_HEAP_MIN_SLOTS =>
'初始堆大小,默认10000,越大需要占用的内存越多'
RUBY_HEAP_FREE_MIN =>
'GC后可用的heap slot的最小值,默认4096,如果太小,就会按照下面2个参数分配新栈'
RUBY_HEAP_SLOTS_INCREMENT =>
'当Ruby需要开辟一片新的堆栈所需的数,默认是10000'
RUBY_HEAP_SLOTS_GROWTH_FACTOR =>
'当ruby需要新的堆栈的时候, 此参数做为一个乘数被用来计算这片新的堆栈的大小'
RUBY_GC_MALLOC_LIMIT =>
'允许不触发GC而分配的C数据结构的最大值,默认8000000 byte,设置的太低就会触发垃圾回收'
}
{
export RUBY_HEAP_MIN_SLOTS=600000
export RUBY_HEAP_SLOTS_INCREMENT=10000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1.8
export RUBY_GC_MALLOC_LIMIT=59000000
export RUBY_HEAP_FREE_MIN=100000
}
{
export RUBY_HEAP_MIN_SLOTS=500000
export RUBY_HEAP_SLOTS_INCREMENT=250000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
export RUBY_GC_MALLOC_LIMIT=50000000
export RUBY_HEAP_FREE_MIN=4096
}
{
export RUBY_HEAP_MIN_SLOTS=10000
export RUBY_HEAP_SLOTS_INCREMENT=10000
export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1.8
export RUBY_GC_MALLOC_LIMIT=8000000
export RUBY_HEAP_FREE_MIN=4096
}
rspec -p
Top 10 slowest examples (3.24 seconds, 42.6% of total time):
User pages index pagination should list each user
1.6 seconds ./spec/requests/user_pages_spec.rb:24
User pages signup with invalid information should not create a user
0.40022 seconds ./spec/requests/user_pages_spec.rb:134
....
RSpec.configure do |config|
# Quick hack to see what our peak number of objects on the heap is
heap_live_num = 0
config.after(:each) do
heap_live_num = [heap_live_num, GC.stat[:heap_live_num]].max
end
config.after(:suite) do
puts "\nMAX HEAP OBJECT COUNT: #{heap_live_num}"
end
end
TEST_SHARDS={
:functionals => [
'test/functional/**/[a-e]*_test.rb',
'test/functional/**/[f-n]*_test.rb',
'test/functional/**/[^a-n]*_test.rb'
],
:integration => [
'test/integration/**/[a-f]*_test.rb',
'test/integration/**/[^a-f]*_test.rb'
],
:units => [
'test/unit/**/[a-i]*_test.rb',
'test/unit/**/[^a-i]*_test.rb'
]
}
TEST_SHARDS.keys.each do |suite|
namespace suite do
TEST_SHARDS[suite].each_with_index do |shard_pattern,i|
shardname = "shard#{i + 1}".to_sym
Rake::TestTask.new(shardname) do |t|
t.libs << "test"
t.pattern = shard_pattern
t.verbose = true
end
Rake::Task["test:#{suite.to_s}:#{shardname.to_s}"].tap do |t|
t.comment = "Run the #{suite.to_s} tests in #{shard_pattern}"
prereqs = ['db:test:prepare']
prereqs += ['ci:setup:testunit'] if ENV.include?('ENABLE_REPORTING')
t.enhance(prereqs)
end
end
end
end