20 Ruby Performance Tips

A lot of bloggers and technologists like to talk about Ruby as if it can’t perform on-par with other dynamic/interpreted programming languages; however, these critics tend to rely on specific benchmarking techniques and ignore the overall performance profile of the language. They also tend not to take into consideration the various factors of their choice of libraries and application architecture before blasting Ruby as being non-performant.

Ruby e Ruby on Rails: scopriamoli nell'intervista a Claudio

Ruby’s various versions and implementations have different performance profiles also and this must be taken into consideration before a decision can be made definitively about Ruby’s overall performance. Benchmarking is a flawed means of determining the real performance of a tool because it relies too heavily on the system configuration on which the tests are ran and what activity is occurring on the system during test runs.

Benchmarks and Ruby-haters not-withstanding you can get good performance from your Ruby applications by following a few simple guidelines. Some of the guidelines are just good programming techniques in general and others are specific to addressing issues in the Ruby language and it’s associated libraries. Performance gains achievable through the implementation of these tips and tricks can range from minimal to breathtaking.

1. Don’t make your code do unnecessary work

For experienced developers this may seem a no-brainer but even old hat coders have been known to slap a class together that might not exactly be the most efficient. Write just enough code to do the job and do it correctly. Don’t over complicate your algorithms and be sure not to do unnecessary things such as looping more than required.

2. Avoid nesting loops more than three levels deep

Nesting not only slows you code down but also can make maintenance of the codebase difficult if it goes too many levels deep. Limiting nesting of loops and functions to three levels or less is a good rule of thumb to keep your code performant.

3. Avoid unnecessary variable assignments

Many people, especially new programmers, tend to assign variables more than necessary. A great example is when someone defines a variable to store a return value and then returns that variable; just return the value directly.

4. Reduce usage of disk I/O

Disk I/O is one of the biggest bottlenecks remaining in computing. Read/write operations to disk are extremely slow and it’s best to avoid using the disk whenever possible. Many people are now using software such as memcached which allows data to be stored in memory and only periodically written to disk. The speed increases when using a memory caching system are tremendous.

5. Use Ruby Enterprise Edition

Ruby Enterprise edition provides up to 33% lower memory usage. In order to take advantage of these performance gains though you must be sure to program according to their guidelines.

6. Avoid method calls as much as possible

Method calls are very expensive operations and should be avoided when necessary.

7. Use efficient Ruby idioms

Program into the language rather than in the language. Performance will suffer if you try to write your Ruby code like you would PHP, Perl, or any other language. Learn the Ruby way of doing things.

8. Use interpolated strings instead of concatenated strings

Interpolated strings are faster than concatenated strings in almost all interpreted languages; Ruby is no exception. Using the << operator makes a method call which and method calls should be avoided when possible.

put “Hello there, #{name}!”


puts “Hello there, ” << name = “!”

9. Destructive operations are faster

Ruby’s in-place methods that modify the actual value instead of working on a copy of it are much faster, but be careful as they sometimes behave strangely (i.e., for!)

10. Avoid unnecessary calls to uniq on arrays

In many cases methods are already calling uniq on an array and there’s no need for you to call it yet again.

11. For loops are faster than .each

When you use .each you encounter per-request execution; for loops avoid this expensive operation.

12. Use x.blank? over x.nil? || x.empty?

When using ActionPack there’s no need for x.nil? or x.empty?; x.blank? checks for both of these.

13. Avoid calls to parse_date and strftime

Both of these are very expensive operations. Use regular expressions when parsing out date/time components.

14. Don’t use unnecessary block parameters

If you won’t be using the parameter in the block don’t specify it in the parameter list. Go through your code and ensure that any parameters declared are used or removed.

15. Know your gems

Not all libraries are created with performance in mind. Many gems are slapped together to solve a particular problem that author was having. Before you introduce a new gem into your performance-oriented production codebase be sure to perform thorough benchmarking and testing against other gems that perform the same tasks.

16. Profile your code regularly

If you profile you code regularly you’ll be able to tell if the latest change to the code will have an adverse effect on performance. Integrate profiling into your testing process and make it automated to ensure that it’s not forgotten. Like unit testing and BDD profiling goes a long way.

17. Improve your algorithms before you try to improve your code

Algorithmic improvements are almost always going to have more of an impact on the performance of your code than tweaks to the way your code is written will. Make sure your algorithm is designed to be efficient and has no extraneous methods or calls. Also, test for most frequent cases first and exit loops as soon as possible.

18. Test the most frequently occurring case first

When using if statements or a case statement always test the cases in the order that they occur most frequently. This allows less code to run before a decision is made. It may not seem like much but over several hundred or thousand runs through the decision logic you’ll notice a definite performance gain.

19. Optimize the way you access global constants

Be sure to precede a global constant with it’s namespace and the double colon operator (Namespace::constant_name) to reduce the time needed to query the library.

20. Use explicit returns

Although Ruby will automatically return the result of the last completed operation if no return value is provided you should use explicit return values. Explicit returns are faster, especially in older Ruby versions such as 1.8.x.

Related Article: