RailsConf 2016
3x Rails: Tuning the Framework Internals

3x Rails: Tuning the Framework Internals

by Akira Matsuda

The video titled '3x Rails: Tuning the Framework Internals,' presented by Akira Matsuda at RailsConf 2016, focuses on performance enhancements within the Rails framework. Inspired by a statement from Yukihiro Matsumoto about Ruby 3.0 being three times faster than Ruby 2, Matsuda discusses various strategies to improve the speed of Rails applications. He empahsizes understanding performance metrics and applying empirical methods to optimize different areas of the framework. Key points covered include:

  • Performance Metrics: Emphasizing the importance of benchmarking tools like Benchmark::IPS to measure performance effectively within Rails applications.
  • Garbage Collection: Matsuda notes that improving garbage collection (GC) could significantly enhance performance; however, recent improvements in Ruby's GC have reduced anticipated overhead.
  • Template Rendering and Action View: He identifies Action View as a common performance bottleneck, suggesting an optimized resolver that caches template filenames to reduce filesystem calls during rendering.
  • Partial Rendering Optimization: Proposing enhancements to the render method to avoid creating unnecessary buffers during partial rendering processes.
  • C Extensions: Discussing the potential benefits of employing C extensions for performance-critical sections of Rails, focusing on memory usage and minimizing temporary object creation.
  • Application Profiling: Advocating for the use of profiling tools to identify bottlenecks, including the built-in TracePoint library.
  • Adapting Rails for Flexibility: Matsuda suggests that Rails could be more modular, similar to Merb, allowing for better customization of performance optimizations to fit specific application needs.

In conclusion, while no magic solution will make Rails three times faster, focusing on optimization strategies and the adaptability of the framework can lead to significant performance improvements across applications.

00:00:09.500 So this talk is titled '3x Rails,' but what does this title mean? This talk is about speeding up the Rails framework. I'm sorry I failed to bring something like a magical patch that makes things three times faster. I kind of planned to do this on stage, but instead, I’d like to discuss some possibilities or points of view. Again, what does the title '3x' mean? Actually, this title is inspired by Mats, you know, dad Ruby, who stated at RubyConf last year that he promised Ruby 3.0 would be three times faster than Ruby 2.
00:00:56.699 So, what's happening? It turns out that it’s quite easy to make Ruby on Rails three times faster. We just need to avoid performance regressions in the Rails side and let Ruby 3 handle the execution, which should naturally make Rails applications three times faster. Anyway, my name is Akira Matsuda. I work on various open-source projects, including the Ruby language and the Rails framework.
00:01:17.880 I also authored and maintain several gem libraries, like CommonRuby, ActiveDecorator, and others. Additionally, I run a local Ruby user group called 'Ruby Kaigi' in Tokyo, which was established in 2008. We meet every Ruby Tuesday, and so far, we have organized 356 meetups. We have many cool members from more than 30 different countries, making it quite a diverse group.
00:02:06.060 We welcome visitors from anywhere, so if you’re interested in joining our user group when you're in Tokyo, please contact me. I'm also organizing a Ruby conference in Japan called 'Ruby Kaigi.' It aims to be the most technical Ruby conference focused on the Ruby language itself.
00:02:34.790 This year, we are having another Kaigi in September in Kyoto. Please note that the conference is not in Tokyo this year; it's in Kyoto, the ancient capital of Japan, which is home to many historical temples, shrines, and gardens.
00:03:02.580 I think Kyoto is the most beautiful city in Japan, so if you haven't had the chance to visit before, I highly recommend attending this year’s conference. The venue looks amazing, featuring a beautiful Japanese garden. We are already selling tickets and the Call for Proposals (CFP) is open, so please check out the official website for more information.
00:03:48.870 Let’s begin the actual talk. As I mentioned earlier, this talk focuses on speeding up the Rails framework, not just your Rails applications. To speed things up, we first need to understand its speed metrics. To measure performance, we usually use benchmarking tools, such as Benchmark::IPS or Ruby’s built-in benchmark library. I prefer Benchmark::IPS because, for example, if you want to measure the performance of your Rails application, you can create a monkey patch to benchmark specific method calls.
00:06:21.380 This approach works by running the request multiple times, although I understand that it's not the best idea as it can produce variations in the score. This way, we benchmark only the Rails part and avoid any browser-related factors. The key question then is: how can we improve that score? One of my practical trials pertains to Ruby’s garbage collection (GC) because everyone knows Ruby GC can be slow. I believe stopping the GC will improve our performance significantly, potentially by 30%.
00:09:01.050 In this case, I used GC.stat calls to observe GC behavior. For instance, we can see reports showing how many iterations occur over a certain time frame. I found that during my benchmark, GC added about 10% overhead instead of the anticipated 30%. This shows that Ruby's GC has recently improved, which is encouraging.
00:10:21.940 Furthermore, with Ruby 2.3, we have new features that can enhance performance, particularly regarding string handling. Strings in Rails used to be a significant concern for the community, especially with regards to inefficient memory usage. I proposed a Ruby magic comment to freeze all string literals without affecting the code's clarity. This was introduced in Ruby 2.3, which could help achieve small performance gains.
00:12:31.660 Moreover, it’s common to think that Ruby is slow because it’s a scripting language and has to parse and compile code every time it runs. However, Ruby 3 introduces features that allow pre-compiling Ruby code into binaries, which can improve load time. I'm not going to delve into this too much since Koichi will cover it in more detail in his talk tomorrow.
00:14:52.440 Next, let's discuss which parts of a simple Rails application are typically slow. It's essential to profile your application to measure performance effectively. We can use profiling software like StackProf or other tools that many might already be familiar with. These tools allow you to dig deeper, and we also have the built-in TracePoint library to help count the number of method calls.
00:16:25.600 As for performance bottlenecks, one area that stands out is Action View, which has some inherent performance issues. The rendering process, for example, involves looking up and compiling templates, which can slow things down.
00:19:05.590 The current template lookup implementation involves calling directory glob for each request, which can become inefficient. I’ve proposed an optimized resolver that caches all template filenames in memory instead of hitting the filesystem for every request. Benchmarks show that this new implementation is significantly faster than the default resolver.
00:22:26.600 Another issue is how Rails handles rendering partials. Each partial can create a new buffer, which can slow down rendering when not necessary. We can rework the render method to optimize for cases where we don’t need a new view context. There’s also potential for sending full path filenames to the render call, allowing the template resolver to skip redundant lookups.
00:31:47.750 Additionally, I have considered enhancing performance through C extensions for certain parts of Rails. Shared code for evaluating how fast parts of Rails can go involves examining non-essential features and ensuring that they don't drag performance down. When thinking about optimal performance, we should focus on memory usage and consider removing unnecessary features from the core classes used like Active Record, which builds many temporary objects.
00:39:09.370 We can potentially construct SQL strings directly from simple queries to avoid overhead with unnecessary Active Record instances. In conclusion, performance bottlenecks vary between applications, and Rails could benefit from increased flexibility to address specific performance needs. Adapting Rails to be more modular, similar to Merb, could help introduce these kinds of optimizations. Thank you for your attention.