Ruby "Speedup" hints?

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

I only have a few hints, like 5… would love to extend it.

So without further ado:

  • Using << instead of += for Strings as += creates a new object
    whereas << will simply work on the current object.

  • Use Inline C for critical methods (had to include that ;> )

  • Reusing variable names might be better than using a lot of
    different variables

  • for is faster than .each on Arrays

  • .last is faster than [0]

  • .zero? is faster than == 0

If you know a few more hints, please add!

On 17.03.2008 13:42, Marc H. wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

I only have a few hints, like 5… would love to extend it.

So without further ado:

  • Using << instead of += for Strings as += creates a new object
    whereas << will simply work on the current object.

I’d replace that with the general rule to avoid object creation because
that will cover more cases (Array#concat vs. Array#+, String#gsub! vs.
String#gsub etc.).

  • Use Inline C for critical methods (had to include that ;> )

You could argue that this does not speed up Ruby code but replaces it
with something else. So it’s questionable whether this item should be
on the list.

  • Reusing variable names might be better than using a lot of
    different variables

Are you talking about a fact or a guess here? You write “might” - which
indicates to me that this is not a proven fact.

  • for is faster than .each on Arrays

  • .last is faster than [0]

I guess you meant Array#last is faster than Array#[-1] or Array#first is
faster than Array#[0].

  • .zero? is faster than == 0

Interesting, I did not know that. But the difference is really small:

[email protected] ~
$ time ruby -e ‘1_000_000.times { 0.zero? }’

real 0m0.748s
user 0m0.468s
sys 0m0.108s

[email protected] ~
$ time ruby -e ‘1_000_000.times { 1.zero? }’

real 0m0.748s
user 0m0.483s
sys 0m0.124s

[email protected] ~
$ time ruby -e ‘1_000_000.times { 0 == 0 }’

real 0m0.869s
user 0m0.561s
sys 0m0.108s

[email protected] ~
$ time ruby -e ‘1_000_000.times { 1 == 0 }’

real 0m0.857s
user 0m0.562s
sys 0m0.124s

[email protected] ~
$

If you know a few more hints, please add!

  • freeze Strings that you are going to use as Hash keys.

Often bad design makes programs slow. While these are valid points
often the bigger effect can be achieved by proper designing an
application (i.e. use a Hash for frequent lookups instead of traversing
an Aarry).

Kind regards

robert

Marc H. wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

I only have a few hints, like 5… would love to extend it.

There is only 1 hint:

PROFILE IT!!!

everything else is BS…

hth

ilan

On Mar 17, 2008, at 9:04 AM, Robert K. wrote:

  • Reusing variable names might be better than using a lot of
    different variables

Are you talking about a fact or a guess here? You write “might” -
which indicates to me that this is not a proven fact.

and it certainly will eventually lead to programmer confusion esp when
dynamically scoped
blocks come into play.

Marc H. wrote:

  • Use Inline C for critical methods (had to include that ;> )

If you know a few more hints, please add!

http://www.informit.com/store/product.aspx?isbn=0321540034

A whole book full of tips!

On Mon, Mar 17, 2008 at 9:22 AM, Ilan B. [email protected] wrote:

There is only 1 hint:

PROFILE IT!!!

+1

All discussions of performance tuning are meaningless without profiling
numbers.

On Mon, Mar 17, 2008 at 11:20:59PM +0900, Avdi G. wrote:

On Mon, Mar 17, 2008 at 9:22 AM, Ilan B. [email protected] wrote:

There is only 1 hint:

PROFILE IT!!!

+1

All discussions of performance tuning are meaningless without
profiling numbers.

Profiling only tells you where performance bottlenecks are. It does
nothing for letting you know how to fix those bottlenecks. That’s where
benchmarks come into play.

Paul

On Mon, Mar 17, 2008 at 12:42 PM, Marc H. [email protected]
wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

I only have a few hints, like 5… would love to extend it.

When generating text output, using StringIO is faster than using puts

On Mon, Mar 17, 2008 at 1:42 PM, Marc H. [email protected]
wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )
If you know a few more hints, please add!

ParseDate#parsedate is expensive - it uses rationals, gcd and other
heavy stuff to convert from [D, M, Y, H, M, S] to timestamp.
Once we did a log merger and we ordered the entries by time. We saved
a lot of processing time by storing the timestamps in the logs along
with the formatted date.
(They were removed afterwards during formatting.)

ERB#new is expensive. Cache compiled templates if they are to be reused.

Use /o switch for Regexp literals that contain constant
#{substitutions} (i.e. that do not depend on function parameters)

On Mon, Mar 17, 2008 at 6:40 PM, Ken B. [email protected] wrote:

On Mon, 17 Mar 2008 14:01:51 +0100, Robert K. wrote:

  • freeze Strings that you are going to use as Hash keys.

Is that in any way a speedup hint? or is it just a safety hint? What
causes the speedup?

Otherwise Hash will dup and freeze the String anyway.

http://ruby-doc.org/core/classes/Hash.html#M002878 (What is not
mentioned there is that frozen strings will not be duplicated.)

On Mon, 17 Mar 2008 14:01:51 +0100, Robert K. wrote:

  • freeze Strings that you are going to use as Hash keys.

Is that in any way a speedup hint? or is it just a safety hint? What
causes the speedup?

–Ken

On Mon, 17 Mar 2008, Marc H. wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

Sounds like time to repost (yet again, can’t we add this to a FAQ
somewhere?)

http://rubygarden.org/Ruby/page/show/RubyOptimization

Please add your hints (preferably with a benchmark to show the
magnitude of the improvement) to that page.

Thanks!

John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand

On Mon, Mar 17, 2008 at 6:08 PM, Paul B. [email protected]
wrote:

This doesn’t make sense. One can easily call #puts on a StringIO
object.

Do you have a concrete example/benchmark that demonstrates the
difference?

Paul

$ time ruby a.rb 10_000_000 > /tmp/a && sleep 3 && time ruby b.rb
10_000_000 > /tmp/b; printf “\a”

real 1m45.305s
user 1m27.581s
sys 0m17.715s

real 0m59.049s
user 0m41.984s
sys 0m16.997s
$ cat a.rb
times = ARGV[0].to_i
times.times { puts “hola mundo” }
$ cat b.rb
require ‘stringio’

times = ARGV[0].to_i
output = StringIO.new
times.times { output.write(“hola mundo\n”) }
output.rewind
print output.read

The difference increases in real world reports.

The difference increases in real world reports.

This and some other tips seem specific to either ruby 1.8 or 1.9.
While StringIO seems much faster with 1.9, in my world, the difference
is rather marginal with 1.8. Also, the following is slightly faster
with 1.8:

times = ARGV[0].to_i
times.times { STDOUT.puts “hola mundo” }

YMMV etc.

On Tue, Mar 18, 2008 at 02:17:22AM +0900, Gerardo S. G?mez Garrido
wrote:

On Mon, Mar 17, 2008 at 12:42 PM, Marc H. [email protected] wrote:

Anyone of you has a few hints on how to speed up ruby code?
(Note - not writing it, but running it :wink: )

I only have a few hints, like 5… would love to extend it.

When generating text output, using StringIO is faster than using puts

This doesn’t make sense. One can easily call #puts on a StringIO
object.

Do you have a concrete example/benchmark that demonstrates the
difference?

Paul

Hi there,

Thanks for the feedback so far. :slight_smile:

"PROFILE IT!!!

everything else is BS."

As for profiling, you can always do profiling of course,
but why copy the efforts others did on it already?

Example - General Statements done such as the one by Robert K.
seem to hold true no matter how much profiling one would do anyway:
“I’d replace that with the general rule to avoid object creation
because
that will cover more cases (Array#concat vs. Array#+, String#gsub! vs.
String#gsub etc.).”

Personally I like such simple truths. :slight_smile:

Sorry for replying so soon but I had to :wink:

"Sounds like time to repost (yet again, can’t we add this to a FAQ
somewhere?)

http://rubygarden.org/Ruby/page/show/RubyOptimization"

I think collecting it in one place would be best for both
newcomers and old rubyistas.

Personally I think all useful things (to a general user
base of ruby) should be collected at the official homepage - or,
in case it would not qualify, there could be links.

External servers should be somewhat reliable too though.
The following result assents me here slightly when I try to
visit above URL … :wink:

"Proxy Error

The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET
/Ruby/page/show/RubyOptimization.

Reason: Error reading from remote server

Apache/2.2.3 (Unix) DAV/2 PHP/5.1.6 SVN/1.1.4 Server at rubygarden.org
Port 80"

Regards

On Tue, Mar 18, 2008 at 6:43 AM, Marc H. [email protected]
wrote:

Personally I like such simple truths. :slight_smile:

The problem with simple truths is that often aren’t simple, and almost
never stay true. There was/is a large percentage of hackers in the
C/C++ community who learned certain “simple truths” about how to make
programs go faster - and continued to use them religiously for
decades, even after the compilers had made those techniques irrelavent
or even detrimental. I believe the same has happened in Java, as
JITing and other optimizations have made a lot of assumptions about
performance moot.

The other problem with “simple truths” is that in performance, it
really isn’t true that every little bit helps. I can’t tell you how
many times I’ve seen a design which was complicated and obfuscated by
some coder’s (potentially superstitious) beliefs about certain
techniques being faster than others (e.g. “always avoid dynamic
dispatch”). Almost invariably it turns out that the real performance
gains to be made are algorithmic and/or have to do with IO, and are
orders of magnitude larger than tiny gains made by following
performance “truths” - to the point that the latter gains are lost in
the statistical noise. It’s often the case that those little
rule-based optimizations only served to make the code more difficult
to refactor, and thus harder to apply the real optimizations to.

At a time in Ruby’s history when it’s implementation is in flux, and
there are multiple alternate implementations coming on line, I think
it is very dangerous to start compiling “rules of thumb” or “simple
truths” about Ruby performance hacks. And when such rules are stated,
they need to be quantified with benchmarks and qualified with very
specific information about the platforms those benchmarks were
gathered on.

…and then you should still write your code to be clear and
well-factored, and put off any optimizations until after you profile.
Chances are you’ll discover that your real slowdown is in IO, or in
some database interaction, not in instantiating objects.

I saw a pertinent quote the other day: “It is easier to optimize
correct code than to correct optimized code.” --Bill Harlan

2008/3/17, Ken B. [email protected]:

On Mon, 17 Mar 2008 14:01:51 +0100, Robert K. wrote:

  • freeze Strings that you are going to use as Hash keys.

Is that in any way a speedup hint? or is it just a safety hint? What
causes the speedup?

As Jano mentioned it’s the skipped #dup for frozen Strings that makes
the speedup.

irb(main):002:0> s=“foo”
=> “foo”
irb(main):003:0> h={s=>1}
=> {“foo”=>1}
irb(main):004:0> [s.object_id, h.keys.first.object_id]
=> [1073545320, 1073545340]
irb(main):005:0> s.freeze
=> “foo”
irb(main):006:0> h={s=>1}
=> {“foo”=>1}
irb(main):007:0> [s.object_id, h.keys.first.object_id]
=> [1073545320, 1073545320]
irb(main):008:0>

Kind regards

robert

On 18.03.2008 15:30, Avdi G. wrote:

performance moot.
Yes, that’s true. But I’m inclined to say that even in Java there is a
single operation that is always the most expensive (not counting IO of
course) and this is object creation. The reason is fairly simple:
object creation has significant overhead (memory allocation or GC,
management overhead for GC) which won’t easily go away - although Sun
has done a tremendous job in improving this throughout the course of JVM
evolution!

rule-based optimizations only served to make the code more difficult
to refactor, and thus harder to apply the real optimizations to.

I could not agree more. In fact, I said the same - just not so well
elaborate as you did. :slight_smile:

At a time in Ruby’s history when it’s implementation is in flux, and
there are multiple alternate implementations coming on line, I think
it is very dangerous to start compiling “rules of thumb” or “simple
truths” about Ruby performance hacks.

Simple truths are so compelling because they are so simple - but they
often are deceptive, too. Just think about the numerous articles about
Java performance (e.g. [1]). Yes, people need to take them with a huge
grain of salt - at least the Ruby version and platform.

And when such rules are stated,
they need to be quantified with benchmarks and qualified with very
specific information about the platforms those benchmarks were
gathered on.

Good point.

…and then you should still write your code to be clear and
well-factored, and put off any optimizations until after you profile.
Chances are you’ll discover that your real slowdown is in IO, or in
some database interaction, not in instantiating objects.

I saw a pertinent quote the other day: “It is easier to optimize
correct code than to correct optimized code.” --Bill Harlan

Great, I have to print that one out! But wait, after optimization
correct code will become optimized code - and sometimes you don’t know
whether it’s still correct (ok, that should be avoided by unit tests).
:slight_smile:

Kind regards

robert

[1] http://www-128.ibm.com/developerworks/java/library/j-jtp09275.html

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs