Ruby performance tips - how to optimize code from the ground upPosted Apr 21, 2020 | 7 min. (1325 words)
Over the last few years, more developers have taken Ruby as their staple programming language. Who can blame them? It certainly has a lot of appealing features. For one, the syntax is easy to read and debug. A default MVC architecture within most Ruby frameworks is another alluring factor that may have had you using it as well.
Despite the long list of advantages, there exists perhaps an equally lengthy list of cons. At the pinnacle of said cons are the low-performance characteristics that every Ruby application shows unless optimized. Many of the reasons for that are due to the nature of the language itself. More about that as you read on. Fortunately, there are some Ruby performance tips worth keeping up your sleeve to make it worth the effort.
If you absolutely must use Ruby as the language when creating applications, this article will help you bypass inherent performance drawbacks. A thorough experience with Ruby will be assumed, although you could use this post to navigate through the decision process of creating your first applications. This will not, however, be a tutorial on setting up an application using Ruby as your coding language.
Ruby performance, from the ground up
Ruby alone can only go so far making modern interfaces and creating complex solutions to everyday problems. In order to squeeze the most from the language, it’s wise to use frameworks.
Now, these are available with pre-existing libraries to help you create applications with Ruby in a faster manner. At the time of writing, close to 20 such frameworks are at our disposal, and the major differences you should take to heart are their performance level variations. Let’s look at just three such frameworks and how opting to go with any of them affects your application’s performance overall. We’ll be using the three frameworks to pass a few requests to identical databases.
Note: For the sole purpose of keeping this post clean and focused on the tips that you’re here for, the implementations of the three frameworks (in which the code is already written and we’d rather not copy it directly into the post) are available when you follow the respective links to their landing pages. It also makes this a fresh and nonintimidating perspective of the ways to make Ruby faster.
Ruby on Rails
Perhaps the most popular at the time of writing is the Ruby on Rails (RoR) framework. It’s packed to the brim with libraries that make deploying your first Ruby application as easy as calling a few lines through a command-line interface of choice. The earlier the version of Rails you use, the less laggy your application will be in terms of refresh rates and query execution times. However, among the three compared here, it’s the slowest option.
This is a simplification of the Rails framework. You could mistake the implementations of Sinatra as simple routing, but it comes with a lot of plugins under the hood. If you’re looking to build Ruby projects that start small and will eventually scale, this is the one to pick. As you may have guessed by now, its performance figures are better than Rails.
Roda is a routing tree web toolkit that allows Ruby developers to create REST APIs very quickly. It takes advantage of a very light implementation of the Ruby language while providing plugins where complexity starts creeping into a project. The main idea for using Roda would be its minimal cognitive overhead. The tree structure of the routes used to create applications with Roda is very easy to read and even simple for interpreters to compile.
A simple representation of the possible numbers of the other Ruby frameworks, along with these three, are shown in the results in the diagram above. Both the memory allocation and requests per second contribute to performance. The tests can be done for your own confirmation using this Git bench repository.
Improving Ruby performance when programming
By now, you’ll have made an informed choice when selecting the framework to use for your Ruby-written application. The next step is making sure you don’t shoot yourself in the foot when actually writing the code. Owing to the way the language was created (using C), it has shortcomings. The major one we’ll shine a light on stems from the advantage it boasts—that everything is based on OOP. You basically have objects everywhere, and that comes with a lot of memory allocation requests as seen on the benchmark results diagram.
You have to utilize efficient code in order to work around this fact. Telling you this may seem obvious, especially if you’ve used other languages before and submitted code for review. However, Ruby is special when written in the conventional (let’s get stuff done and go home) way. You create a lot of bottlenecks that don’t flag as bugs but show up when you review for performance. The level of efficiency that you can attain largely depends on your experience with Ruby as a language. It also depends upon how much time you have. So you can go through the documentation and find the best ways to avoid creating code that asks for more memory each time it runs. Functions tend to do that in Ruby. So let’s cover some Ruby performance tips to abide by while you’re developing applications.
Ruby performance tips
Don’t write code from scratch if there exists a gem for the same end result. Usually, the gems contain optimized code. Not only will the code run faster, but it also gets onto the IDE faster.
If your application requires a lot of requests to be passed to the database, use the database features to handle these. Databases often come with more tools than we use. Try them out.
A lot of veteran developers go on and patch Ruby’s GC. It may not add noticeable effects on small websites, but it helps with speed when your application scales.
The most important tip is to have a way of telling when something you just added has caused a performance drop. You can do this using an APM throughout the development phase.
Using an APM to monitor Ruby performance
An application performance monitoring (APM) tool, such as Raygun’s, allows you to keep a persistent watch on how your coding affects performance. In reality, you could whip up a “hello world” app and build a proper website from that skeleton. But when using well-placed plugins and calling on views that show usable data to the end user, the code itself is of less concern than making sure that runtime performance is optimal for a delightful experience. You need to know which queries are responsible for pages running slowly and when to use lazy loading based on the actual times the page (and its resources) are requested by users. An APM will show you all this, and in the case of Raygun’s APM, it also tells you why a part of your code is slow.
This changes the entire problem from being a language-centered issue into what you’re willing to do to get the code running smoothly. The Ruby framework of choice does come into play. Coupled with a quick executing option, an APM will further enhance your ability to make your application enjoyable when it reaches your intended users. As the language evolves and new frameworks emerge, it’ll still have the ability to look under the hood while an audience runs the app that allows senior Ruby programmers to make their applications stand out.
Perhaps the best tip when it comes to Ruby’s performance as a programming language is to keep a close eye on how each choice made when coding affects the overall speed of execution through an effective APM.
Application Performance Monitoring for Ruby is coming to Raygun soon! Ruby teams will soon be able to get end to end monitoring with features like detailed trace transactions, dashboards, user experience monitoring, and more. Learn more here.