It does, and it is the only inject form I consider valid. However, converting it to map leads to a 20-25% reduction in time.
Ara's pack/unpack is always what I intuitively reach for in a problem like this, but it turns out to be more expensive than a simple map/left-shift form. IPAddr is very powerful, but there is a cost to that power (parsing every IP form under the sun). If I needed anything more than JUST converting to/from ints I'd use IPAddr.
# of iterations = 100000
user system total real
null_time 0.020000 0.000000 0.020000 ( 0.017184)
split/map/<<+ 1.040000 0.000000 1.040000 ( 1.042783)
split/map/pack/unpack 1.180000 0.000000 1.180000 ( 1.177197)
split/inject/<<+ 1.310000 0.000000 1.310000 ( 1.308850)
split/inject/+* 1.430000 0.010000 1.440000 ( 1.436653)
split/inject/+*= 1.640000 0.000000 1.640000 ( 1.637948)
split/zip/inject/+* 2.290000 0.000000 2.290000 ( 2.288469)
ohdeargodno 2.670000 0.000000 2.670000 ( 2.678789)
ipaddr/to_i 3.940000 0.010000 3.950000 ( 3.950504)
# of iterations = 1000000
user system total real
null_time 0.130000 0.000000 0.130000 ( 0.131523)
split/map/<< 10.490000 0.010000 10.500000 ( 10.578584)
split/map/pack/unpack 12.360000 0.010000 12.370000 ( 12.383726)
split/inject/<< 14.130000 0.030000 14.160000 ( 14.202936)
split/inject/+* 15.700000 0.040000 15.740000 ( 15.872160)
split/inject/+*= 18.000000 0.050000 18.050000 ( 18.176626)
split/zip/inject/+* 25.290000 0.060000 25.350000 ( 25.530274)
ohdeargodno 28.350000 0.070000 28.420000 ( 28.551007)
ipaddr/to_i 41.570000 0.080000 41.650000 ( 41.822529)
#!/usr/bin/env ruby -w
require 'benchmark'
require 'ipaddr'
max = (ARGV.shift || 1_000_000).to_i
puts "# of iterations = #{max}"
Benchmark::bm(22) do |x|
x.report("null_time") do
for i in 0..max do
# do nothing
end
end
x.report("split/map/<<+") do
for i in 0..max do
ip = 0
"127.0.0.1".split('.').map { |n| ip = (ip << 8) + n.to_i }
end
end
x.report("split/map/pack/unpack") do
for i in 0..max do
"127.0.0.1".split(".").map{|s| s.to_i }.pack("C*").unpack("N")
end
end
x.report("split/inject/<<+") do
for i in 0..max do
"127.0.0.1".split('.').inject(0) { |s,n| (s << 8) + n.to_i }
end
end
x.report("split/inject/+*") do
for i in 0..max do
'127.0.0.1'.split('.').inject(0) { |t,v| v.to_i + t*256 }
end
end
x.report("split/inject/+*=") do
for i in 0..max do
"127.0.0.1".split(".").inject(0) { |s,i| s+=i.to_i; s *= 256 } / 256
end
end
x.report("split/zip/inject/+*") do
for i in 0..max do
'127.0.0.1'.split(".").zip([256**3,256**2,256,1]).inject(0) { |sum, a| sum + a[0].to_i*a[1] }
end
end
x.report("ohdeargodno") do
for i in 0..max do
"127.0.0.1".split(".").map { |i| i.to_i }.reverse.inject() { |memo, part| memo << part * (256 ** memo.size) }.inject(0) { |memo, part> memo += part }
end
end
x.report("ipaddr/to_i") do
for i in 0..max do
IPAddr.new( '127.0.0.1' ).to_i
end
end
end
···
On Feb 20, 2008, at 11:50 , Alex Shulgin wrote:
On Feb 20, 3:38 am, Tiago Pinto <thpi...@gmail.com> wrote:
What do you think? There's a way to do this? Is this just a silly question?
I know, we should be working, but we both love Ruby.
Everybody replied already, still I think left-shift deserves
mentioning:
"127.0.0.1".split('.').inject(0) { |s,x| (s << 8) + x.to_i }
=> 2130706433