Forum: Ruby Re: How convert an integer to a bit array

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 daniels (Guest)
on 2005-11-24 00:18
(Received via mailing list)
>> 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.
#####################################################################################
822a498b26a2cb7d1f0f2e7e37ce61b2?d=identicon&s=25 ed.howland (Guest)
on 2005-11-24 00:30
(Received via mailing list)
On 11/23/05, Daniel Sheppard <daniels@pronto.com.au> 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
This topic is locked and can not be replied to.