Rails Performance Unveiled: Identifying Common Culprits
When it comes to improving application performance and areas to focus on, I would recommend looking at the APM data, and then deciding which areas to prioritize.
However this article isn’t about where to focus efforts, but rather a compilation of techniques to improve your application’s performance, from tackling common problems like N+1 queries and database indexing to leveraging the
jemalloc memory allocator. Let’s look at these performance-boosting strategies designed to fine-tune your application.
Different strategies to improve the performance of the application
One of the most common problems I see when working on improving the performance of Rails applications is the presence of an N+1 query. Most times they are not hard to solve. However, it can be hard to track down what code is triggering the N+1 queries. Sometimes they are wrapped up in the view files, and some in the
before_action functions. The impact of the N+1 query depends on how big the tables are that are involved in the query, and how many times that query is called.
Missing db indexes / Wrong indexes
Another area prone to performance bottlenecks lies within the database. It is quite common to not think about what indexes the table should have when one is creating the model and writing its migration. But as time goes on and the database tables keep getting larger and the queries get complex, one of the most common problems is that the queries take a long time to return a result from the database. And once that happens, one of the common reasons is that the queries are not using any sort of indexing to make the fetching of data faster. And if indexes do exist, they might not be applied to the fields of interest. You might be querying on a field called state in the users table but you have indexed the table on a column other than state. This can also lead to slower queries.
Increasing memory usage
Escalation in memory usage stands out as a prevalent challenge in Ruby on Rails applications, where the increase can be sudden or gradual. Finding the root cause of the memory issues could be one of the hardest things to debug.
A solution worth trying, before you dig any further into understanding the reason for increased memory usage, is to switch to the Jemalloc memory allocator . In a lot of instances, it has been reported that the memory usage was reduced by up to 50% just by changing the memory allocator from Malloc to Jemalloc. But if you do end up applying this, we would recommend always observing the memory usage pattern for a few days. A thing worth noting is that Jemalloc will solve the memory bloat problem, but will not solve the memory leak problem you might be facing. For memory leaks, you will have to find out where the leak is coming from in the code and then fix the code.
defer that can be used depending on different scenarios and it can have an impact on how fast the page loads.
A common yet overlooked factor contributing to sub-optimal Rails performance is the use of underprovisioned servers. An underprovisioned server may not be able to handle increasing traffic on your application, suffer from ever increasing memory usage, server restarts, slow response on database queries, and impacting overall user experience. APMs can help in identifying the problem and also act as a feedback loop when the servers are upgraded.
While this post barely scratches the surface of these techniques, I hope that it gives you ideas on what optimizations to apply to your application. Need help improving your application’s performance? Check out Tune Report and send us a message today! .