From: David Masover Date: 2009-11-26T01:51:07+09:00 Subject: Re: Ruby internals & other questions On Wednesday 25 November 2009 10:01:02 am Ralph Shnelvar wrote: > Is there a document or website that describes how Ruby works? You're going to have to get a lot more specific. > y=0 > 1_000_000.times {|x| y+=x} > > (1) Does the block get compiled a million times? Implementation-specific, but I doubt it. > (2) What's the best Ruby way to do a sum from 1 to 1_000_000 What do you mean by "best"? Your way probably won't work, by the way -- it will count from 0 to 999_999, not from 1 to 1_000_000. This is probably the most idiomatic way: (1..1_000_000).inject(&:+) But if you mean the fastest way, I would guess it would be something like this, in pure ruby: y = 0 i = 0 while i < 1_000_000 i += 1 y += i end Realistically, though, Ruby probably isn't the best language. Inline C might be better: require 'inline' class Foo inline do |builder| builder.c <<-END long sum(long max) { long result = 0; long i; for(i=1; i<=max; i++) { result += i; } return result; } END end end puts Foo.new.sum(1_000_000) To be fair, this takes longer on my system, but I think that's because the C compiler is being run each time. I'm sure there's a way to avoid that, but I haven't looked. This is also going to be much more difficult for you on Windows than, well, any other platform. But you should keep some things in mind -- this is a really arbitrary benchmark, of the sort that you'd never actually use in real code. Try this instead: n = 1_000_000 n*(n+1)/2 The way to be faster in any language is to improve your algorithm -- and your algorithm is much more likely to be a bottleneck than the language in question. That's why I use Ruby in the first place. > (3) Is there a difference in speed between IRB.exe and ruby.exe in > executing the above code? Maybe. If both are from the same version of Ruby, there shouldn't be anything significant. You could test it, though. > (4) In IRB, whats the best way to time the code, above? The simplest way is: require 'benchmark' require 'foo' # if you do the RubyInline example I gave Benchmark.bm do |x| x.report { Foo.new.sum(1_000_000) } x.report { y = 0; 1_000_001.times {|x| y += x} } x.report { (1..1_000_000).inject(&:+) } x.report { n = 1_000_000; n*(n+1)/2 } end That'll work anywhere, though it's going to be a bit cumbersome in irb. Someone else may have a "best" way. I haven't run this test, though. I have no plans to, unless someone really wants to claim that any of the loops are faster than those three integer operations.