Ruby Weekly is a weekly newsletter covering the latest Ruby and Rails news.

Six Quick Optimization Tips for the Ruby Interpreter

By Peter Cooper / July 11, 2008

Ilya Grigorik of Igvita has put together a great article called 6 Optimization Tips for Ruby MRI. In it, he walks through six different things you can do to improve the performance of your code when running on the regular Ruby interpreter (MRI). For example, interpolation is quicker than concatenation when working with strings, destructive operations prevent wasteful object duplication, and hand-written blocks are a lot faster than Symbol#to_proc.

And.. metaprogramming, of course, comes in for some much deserved performance criticism:

Ruby has a wonderful property of being highly dynamic, which in turn, allows us to create all kinds of spectacular meta-programming scenarios. However, this comes at a price of minimal runtime and compile time optimization (JRuby and some other VM's are changing this). Unlike most other languages, Ruby's MRI does not generate bytecode (Ruby 1.9 will change this), but relies solely on searching through the Abstract Syntax Tree (AST) for virtually every method call, variable, and so on. Sounds expensive? It is. Hence, next time you're saving yourself three lines of code by writing a meta function, consider inlining the logic directly.

From personal experience, I know there are a lot of alternative coding techniques you can use to shave off valuable milliseconds here and there in Ruby. If you have any to share, post a comment, and I'll be putting together my own compilation of tips on Ruby Inside in the near future.

Comments

  1. Dave says:

    Surely if we wanted to shave off valuable milliseconds we'd be using C rather than Ruby. Rubyists optimize their code for beauty (and maintainability) rather than speed or size.

  2. Jan Wedekind says:

    Cool! I didn't know about the benchmarking extension (I was using Time.new.to_f so far).
    I've noted that Range::min and Range::max are very slow. Just try to execute the following line of code:

    (1...2**22).max

    For integers it is better to use Range::begin and Range::end-1. You can also simply override the methods like this:

    class Range
    alias_method :orig_min, :min
    alias_method :orig_max, :max
    def min
    if Integer === self.begin
    self.begin
    else
    orig_min
    end
    end
    def max
    if Integer === self.end
    exclude_end? ? self.end - 1 : self.end
    else
    orig_max
    end
    end
    end

Other Posts to Enjoy

Twitter Mentions