Showing posts with label tips. Show all posts
Showing posts with label tips. Show all posts

Friday, August 13, 2010

Benchmarking any rake task

While writing serializable_proc, i wanted to find out how the RubyParser-based implementation fair against ParseTree-based one, here's a rake task i've written to support the following use cases:

# yield benchmark results by running :spec task x5 (default)
$ rake benchmark[spec]

And:

# yield benchmark results by running :spec task x2
$ rake benchmark[spec,2]

And here's the code to acheive the above:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Benchmarking
task :benchmark, :task, :times do |t, args|
times, task = (args.times || 5).to_i.method(:times), args.task
title = " ~ Benchmark Results for Task :#{task} ~ "
results = [%w{nth}, %w{user}, %w{system}, %w{total}, %w{real}]

# Running benchmarking & collecting results
require 'benchmark'
times.call do |i|
result = Benchmark.measure{ Rake::Task[task].execute }.to_s
user, system, total, real =
result.match(/^\s*(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+\(\s*(\d+\.\d+)\)$/)[1..-1]
["##{i.succ}", user, system, total, real].each_with_index{|val, j| results[j] << val }
end

# Formatting benchmarking results
formatted_results = results.map do |rs|
width = rs.map(&:to_s).map(&:size).max
rs.map{|r| ' ' + r.ljust(width, ' ') }
end.transpose.map{|row| row.join }

# Showdown .. printout
line = '=' * ([title.size, formatted_results.map(&:size).max].max + 2)
puts [line, title, formatted_results.join("\n"), line].join("\n\n")

end

And here's the output i get for the x2 run:

...
(blah blah, the output of running :spec task x2)
...
===============================================

~ Benchmark Results for Task :spec ~

nth user system total real
#1 0.000000 0.000000 1.030000 1.052567
#2 0.000000 0.000000 1.020000 1.040352

===============================================

Wednesday, August 4, 2010

Bitten by Array#*

Have u tried Array#* ? Its a pretty cool way to return an array, built by concatenating the original array by n times:
1
2
3
4
5
a = [1] * 2
p a # >> [1, 1]

a = %w{a} * 2
p a # >> ["a", "a"]

However, u should be aware that all elements of the new array actually points to the same instance, as proven by their object_id:
1
2
3
4
5
x = 'a'
p x.object_id # >> 70212363949780

a = [x] * 2
p a.map(&:object_id) # >> [70212363949780, 70212363949780]

This means that:
1
2
3
4
5
6
7
8
9
10
11
12
13
# Reassigning one element does not affect another
a = %w{a} * 2
p a.map(&:object_id) # >> [70058328018360, 70058328018360]
a[0] = a[0].sub('a','b')
p a # >> ["b", "a"]
p a.map(&:object_id) # >> [69915340242120, 69915340242360]

# In-place manipulating one element affects another
a = %w{a} * 2
p a.map(&:object_id) # >> [70058328018360, 70058328018360]
a[0].sub!('a','b')
p a # >> ["b", "b"]
p a.map(&:object_id) # >> [70058328018360, 70058328018360]

Labels