Posted by pratik
on Saturday, February 02
I’ve always been in the habit of maintaining a file called crap.rb under my home directory, which I mainly use for benchmarking and testing some tiny stuff. So here are some amusing/useful benchmarks from my crap( :?\.rb), the only file where I use __END__ !
The irregular Regular Expressions
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
|
require 'benchmark'
n = 1000000
s = "hey hello world"
r1 = Regexp.new(/hello/)
r2 = /hello/
Benchmark.bm do |x|
x.report("Regxp.new ") { n.times { s =~ r1 } }
x.report("Funky slash ") { n.times { s =~ r2 } }
x.report("No Object ") { n.times { s =~ /hello/ } }
x.report("Regxp.new match ") { n.times { r1.match(s) } }
x.report("Funky match ") { n.times { r2.match(s) } }
x.report("No Object match ") { n.times { /hello/.match(s) } }
end
null:~ lifo$ ruby crap.rb
user system total real
Regxp.new 0.570000 0.000000 0.570000 ( 0.584298)
Funky slash 0.600000 0.000000 0.600000 ( 0.599363)
No Object 0.450000 0.010000 0.460000 ( 0.454105)
Regxp.new match 1.340000 0.000000 1.340000 ( 1.353320)
Funky match 1.350000 0.010000 1.360000 ( 1.352977)
No Object match 1.340000 0.000000 1.340000 ( 1.357741) |
Various http client libraries
This is one of my favorites.
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
['rubygems', 'benchmark', 'eventmachine', 'net/http', 'open-uri', 'rfuzz/session'].each {|lib| require lib }
server = 'localhost'
port = 9292
request_uri = "http://#{server}:#{port}/"
def run(name, x)
x.report(name) do
100.times do
yield
end
end
end
uri = URI.parse(request_uri)
puts Net::HTTP.get(uri)
rfuzz = RFuzz::HttpClient.new(server, port)
puts rfuzz.get('/').http_body
puts open(request_uri).read
EM.epoll
http = nil
EM.run do
http = EM::Protocols::HttpClient2.connect(server, port).get("/")
http.callback { EM.stop }
end
puts http.content
EM.run { EM::Protocols::HttpClient2.connect(server, port).get("/").callback { EM.stop } }
Benchmark.bm do |x|
run("Ruby Net::HTTP ", x) do
Net::HTTP.get(uri)
end
run("Open URI ", x) do
open(request_uri).read
end
run("RFuzz ", x) do
rfuzz.get('/').http_body
end
run("Event Machine ", x) do
EM.run { EM::Protocols::HttpClient2.connect(server, port).get("/").callback { EM.stop } }
end
end
user system total real
Ruby Net::HTTP 0.090000 0.070000 0.160000 ( 7.380255)
Open URI 0.160000 0.100000 0.260000 ( 7.816298)
RFuzz 0.050000 0.050000 0.100000 ( 7.988522)
Event Machine 0.040000 0.020000 0.060000 ( 0.186210) |
Camelize
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
require 'benchmark'
require 'strscan'
n = 100000
u = "hello_world/whatever"
class String
# From rails
def camelize
self.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
end
# From merb
def mamelize
new_string = ""
input = StringScanner.new(self.downcase)
until input.eos?
if input.scan(/([a-z][a-zA-Z\d]*)(_|$|\/)/)
new_string << input[1].capitalize
new_string << "::" if input[2] == '/'
end
end
new_string
end
def lamelize
self.split('/').map { |ss| ss.split('_').map { |sub| sub.capitalize }.join }.join('::')
end
def damelize
self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
end
end
puts u.camelize
puts u.mamelize
puts u.lamelize
puts u.damelize
Benchmark.bm do |x|
x.report("Camelize") do
n.times { u.camelize }
end
x.report("Mamelize") do
n.times { u.mamelize }
end
x.report("Lamelize") do
n.times { u.mamelize }
end
x.report("Damelize") do
n.times { u.damelize }
end
end
user system total real
Camelize 1.600000 0.010000 1.610000 ( 1.616453)
Mamelize 1.560000 0.000000 1.560000 ( 1.635481)
Lamelize 1.560000 0.010000 1.570000 ( 1.578037)
Damelize 1.480000 0.010000 1.490000 ( 1.486758) |
Posted by pratik
on Thursday, September 27
Burn/donate/throw away all your ruby/rails books
1
2
3
4
5
6
7
8
|
lifo:~/Rails pratik$ ruby ~/Rails/rails/railties/bin/rails foobar
lifo:~/Rails pratik$ cd foobar
lifo:~/Rails/foobar pratik$ svn co http://dev.rubyonrails.com/svn/rails/trunk vendor/rails
lifo:~/Rails/foobar pratik$ cd vendor/rails/
lifo:~/Rails/foobar/vendor/rails pratik$ find . | grep .rb$ | xargs perl -pi -e 's/^\s*?#.*?$//'
lifo:~/Rails/foobar/vendor/rails pratik$ cd ../../
lifo:~/Rails/foobar pratik$ rake doc:rails
lifo:~/Rails/foobar pratik$ open doc/api/index.html
|
And you’ll know the difference in 15 days.
Have fun.
Posted by pratik
on Thursday, September 06
Let’s ignore the ducks.
1
2
3
4
5
6
7
8
9
10
|
def amazing(id)
case id
when :first then "I am first!"
when :all then "All!"
when Integer then "That should just be fine"
when String then "No strings attached"
when true then "Fine. You are right"
else raise "Stop being a jerk!"
end
end |
Oh! I love my ducks. Ducks are the ruby way! and only ruby way to do it. Fascism!
1
2
3
4
5
6
7
8
9
10
|
def amazing(id)
case
when id == :first then "I am first!"
when id == :all then "All!"
when id.respond_to?(:integer?) && id.integer? then "That should just be fine"
when id.respond_to?(:to_str?) && id.to_str? then "No strings attached"
when id == true then "Fine. You are right"
else raise "Stop being a jerk!"
end
end |
Ok. Get rid of naked “case” statement. No no, not facism. I’d say Ignorance
1
2
3
4
5
6
7
8
9
|
def amazing(id)
if id == :first then "I am first!"
elsif id == :all then "All!"
elsif id.respond_to?(:integer?) && id.integer? then "That should just be fine"
elsif id.respond_to?(:to_str?) && id.to_str? then "No strings attached"
elsif id == true then "Fine. You are right"
else raise "Stop being a jerk!"
end
end |
Open question
Which way would you choose ? I’d choose the first one and I’d go even further to say that duck typing is over hyped and it all depends on the context where it’s being used. One really needs to have an open mind to accept that there are more than one ways to do it else you should be where you actually belong
Posted by pratik
on Tuesday, August 14
Ruby never stops to surprise me.
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
27
28
29
30
31
|
class Object
def _(method, *args)
if self.class.private_instance_methods.include?(method.to_s)
send(method, *args)
else
raise "Stop acting like hasslehoff!!"
end
end
end
class Hello
def hey
puts "New world order!"
end
private
def secret(foo, bar)
puts "#{foo} is not #{bar}"
end
def hasslehoff
puts "acts_as_hasslehoff ftw!"
end
end
h = Hello.new
h._ :secret, "hello", "world"
h._ :hasslehoff
h._ :hey, "srsly?" rescue puts "yay!" |
Call the private methods all you want. But at least do it the right way ;-)
Posted by pratik
on Saturday, June 30
UPDATE : Check Ticket 8818
Welcome to my new blog :) Now over to rails..
So you’ve been told about using cute shortcuts for enumerator like Post.find(:all).map(&:title) – you feel great using it, don’t you ?? And you laughed at those who didn’t understand how &:sym worked and continued to use .map ( |shit| shit.stupid } syntaxt! You were made feel geeky indirectly. I was there :-)
But those days are “over” and it’s time to go back home!
I’d let benchmark speak for me..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
require 'benchmark'
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
n = 10000
s = Struct.new :id
messages = []
n.times { messages << s.new(:id => rand(n)) }
Benchmark.bm do |x|
# Integer
x.report { n.times { messages.map{|m| m.id} } }
x.report { n.times { messages.map(&:id) } }
end
# $ ruby perform.rb
# user system total real
# 33.280000 0.860000 34.140000 ( 34.912584)
# 191.940000 1.660000 193.600000 (197.168849) |
Need I say anymore ? Wake up and smell the coffee.
Related ticket