# Re: How convert an integer to a bit array

#1

bits = Array.new(8) { |i| 7[i] }.reverse!

This code will call:
Integer#[] 8 times
Array.new once
Array.reverse! once

def to_ba(num, size=8)
(-size+1…0).inject({}) {|x,i| x << num[-i]} end

This code will call:
Integer#[] 8 times
Array.new twice

Range.new once
Integer#@- once
Integer#+ once
Array#inject once
Array#<< 8 times

All those calls are slower than the single call to Array.reverse!

Or perhaps, modifying James’:

def to_ba(num, size=8)
Array.new(size) {|i| num[-i+size-1]}
end

Integer#[] 8 times
Array.new once

Integer#@- 8 times
Integer#+ 8 times
Integer#- 8 times

Once again, those extra calls take longer than the single call to
Array#reverse!.

It’s an easy trap to fall into - experience in most other languages
teaches you that simple operations on primitives are much faster than
calling of to a method. The problem with porting that knowledge to ruby
is that there are not operations on primitives - everything is going
through the method dispatching.

I believe most (all?) of the methods above are implemented in C - best
thing you can do for your code is to make it faster is to spend the
least amount of time possible in ruby-land - in 99% of situations, one
call to C code will outperform anything that takes more than 1 call to
get to C code (it’s only if the algorithm in the C code is drastically
bad that you’ll be able to outperform it, and I trust that ruby’s code
core contains no algorithms that bad).

24 calls through the message dispatching or 1 call through message
dispatching - it’s easy to see the speed improvement.

Benchmark.bm(10) {|bm|
bm.report(‘james’) {100000.times {Array.new(8) { |i| 7[i] }.rev
bm.report(‘ed1’) {100000.times {(-8+1…0).inject([]) {|x,i| x <<
7[-i]}}}
bm.report(‘ed2’) {100000.times {Array.new(8) {|i| 7[-i+8-1]}}}
}
user system total real
james 0.781000 0.000000 0.781000 ( 0.781000)
ed1 2.859000 0.000000 2.859000 ( 2.922000)
ed2 1.219000 0.000000 1.219000 ( 1.250000)

#####################################################################################
This email has been scanned by MailMarshal, an email content filter.
#####################################################################################

#2

On 11/23/05, Daniel S. removed_email_address@domain.invalid wrote:

It’s an easy trap to fall into - experience in most other languages
teaches you that simple operations on primitives are much faster than
calling of to a method. The problem with porting that knowledge to ruby
is that there are not operations on primitives - everything is going
through the method dispatching.

I saw that you were right. I used require ‘benchmark’ and 100,000 and
1M size arrays. I guess I was assuming, as you say, that my
optimization to primative operations ((-), and +) would be faster, but
in fact actually increased the amount of time in Ruby land.

Thanks for the insight. What makes that great, is the knowledge that
writing code the way you think about a problem, may in fact be the
ultimate solution.

Ed