15 Jul, 2009, Runter wrote in the 1st comment:
Votes: 0
1.9 brings a lot of speed increase. In some cases up to 4 times as fast. Ruby is already fast enough for many applications like MUDs– (It's very fast with string parsing, especially with regular expressions.) Putting that aside, some people may want to know how to get additional performance. The best way I've found to do this is to understand costs of actual practices. A lot of Ruby users optimize their code for elegance and readability. I'm no different, really, but these are good things to know about in general–especially when it won't take away from elegance or readability.

1. Benchmark code! Ruby makes it very easy to profile and benchmark code. Often times you'll find surprising results.
require 'benchmark'

Benchmark.bm do |b|
b.report("with copy") { 100000.times do ; hash = {}; hash = hash.merge({10 => 200}); end }
b.report("no copy") { 100000.times do ; hash = {}; hash.merge!({10 => 200}); end }
end

# user system total real
# copy 0.460000 0.180000 0.640000 ( 0.640692)
# no copy 0.340000 0.120000 0.460000 ( 0.463339)


2. Use ! operations. I alluded to it above.

hash.merge is more expensive than hash.merge!. str.sub is more expensive than str.sub!. That can be said for virtual all of the destructive methods. That's because of data being duplicated. Depending on the data (especially with big strings) this can make a noticeable difference. Don't write your code around this—But if you find yourself able to use either–Go with ! methods.

3. Native str subs are your friend.
puts "Name: #{first_name} #{last_name}"  # faster
puts "Name: " << var1 << var 2 # slower


4. Avoid needless lookups

This especially rings true in 1.8x but look at this.
@var = "uses a single lookup, because of caching"
self.var = "results in multiple lookups"


5. Avoid reinventing the wheel

When available use the built-in classes and methods. This isn't just to lower man hours—They're optimized and often/always written in C rather than pure ruby. This makes a *great* deal of difference. Even sometimes piggy backing your algorithms with the standard libraries is a better idea than rewriting something to get additional functionality in pure ruby. (Like any of the string parsing methods, for example.)
15 Jul, 2009, elanthis wrote in the 2nd comment:
Votes: 0
Pretty much good advice for just about all languages, but it's nice to see the specifics brought up for Ruby users. Good post.
15 Jul, 2009, Kline wrote in the 3rd comment:
Votes: 0
Preformance is for win.

All your posts slowly intrigue me more about Ruby, though, with such handy built-in tools you'd look to 3rd party sources for in other languages.
15 Jul, 2009, David Haley wrote in the 4th comment:
Votes: 0
The "batteries included" aspect of Ruby (and Python) is one of the nicest features of the languages. Lua suffers from not having "batteries included". Lua's strengths are elsewhere, though, in areas where (IMO) the other languages sometimes aren't as nice.
15 Jul, 2009, Runter wrote in the 5th comment:
Votes: 0
Kline said:
Preformance is for win.


I don't know what you could be referring to. :)
17 Jul, 2009, Runter wrote in the 6th comment:
Votes: 0
Chris Bailey said:
Another interest thing to note is that strings contained inside " " are slower (not by much) than strings inside ' ', because using double quotes will check to see if it needs to expand variables for interpolation etc..
name = "Bob"
str1 = "Hello #{name}!"
str2 = 'Hello #{name}!'
puts str1 # Hello Bob!
puts str2 # Hello #{name}!


Seemed to fit here.

edit: Although I cannot confirm it makes much of a difference. Although it seems like it would certainly.
17 Jul, 2009, Kline wrote in the 7th comment:
Votes: 0
require 'benchmark'
Benchmark.bm do |b|
b.report("with single") { 100000.times do ; name = "Bob"; str1 = 'Hello #{name}!'; end }
b.report("with double") { 100000.times do ; name = "Bob"; str2 = "Hello #{name}!"; end }
end

user     system      total        real
with single 0.300000 0.020000 0.320000 ( 0.358628)
with double 0.500000 0.040000 0.540000 ( 0.573899)
17 Jul, 2009, Chris Bailey wrote in the 8th comment:
Votes: 0
Right on Kline, I would recommend that you use Benchmark.bmbm instead, it runs everything twice with the first being a rehearsal, to make sure garbage collection doesn't mess up your results.

require 'benchmark'

n = 10000000
Benchmark.bmbm do |x|
x.report("Single Quote") { n.times {"Hello"} }
x.report("Double Quote") { n.times {'Hello'} }
end


christopher@deb-server:~/repository$ ruby1.9 thing.rb 
Rehearsal ————————————————
Single Quote 4.730000 0.000000 4.730000 ( 4.724137)
Double Quote 4.800000 0.000000 4.800000 ( 4.796206)
————————————— total: 9.530000sec

user system total real
Single Quote 4.730000 0.010000 4.740000 ( 4.732299)
Double Quote 4.810000 0.000000 4.810000 ( 4.806372)
christopher@deb-server:~/repository$
17 Jul, 2009, Scandum wrote in the 9th comment:
Votes: 0
Kline said:
All your posts slowly intrigue me more about Ruby, though, with such handy built-in tools you'd look to 3rd party sources for in other languages.

It's fairly easy to build your own cpu monitor and debugger in C, or rip the code out of a codebase (emud) that has it.

I must say I'm slightly put off by what I'm seeing because Ruby looks like a syntactical nightmare, though that could be my C background. That benchmark tool is pretty nifty.
17 Jul, 2009, kiasyn wrote in the 10th comment:
Votes: 0
Scandum said:
Kline said:
All your posts slowly intrigue me more about Ruby, though, with such handy built-in tools you'd look to 3rd party sources for in other languages.

It's fairly easy to build your own cpu monitor and debugger in C, or rip the code out of a codebase (emud) that has it.

I must say I'm slightly put off by what I'm seeing because Ruby looks like a syntactical nightmare, though that could be my C background. That benchmark tool is pretty nifty.


but the point is /you dont have to/.
17 Jul, 2009, David Haley wrote in the 11th comment:
Votes: 0
It seems that a fairer test would have both doing the concatenation: in that benchmark (that Kline posted), you're not actually testing the same thing. Chris's benchmark in #8 is a better benchmark.

It's interesting to note that the Ruby compiler should be able to optimize that away at compile-time as it can see that there will never be string substitution to do in that literal. Just one more optimization for them to do, eventually.

EDIT: I think that Kiasyn is saying that you don't have to build your own profiling tool, and isn't replying to Scandum's second note…
17 Jul, 2009, Runter wrote in the 12th comment:
Votes: 0
I must say I'm slightly put off by what I'm seeing because Ruby C++ looks like a syntactical nightmare, though that could be my C background. That benchmark tool STL is pretty nifty.
0.0/12