Rails Internals

Summarized using AI

Closing Keynote: Code Required

Aaron Patterson • June 20, 2015 • Earth

In his closing keynote at GoRuCo 2015, Aaron Patterson, a prominent member of the Ruby and Rails core teams, delivered an insightful talk titled "Code Required," where he explored performance issues related to loading files in Ruby.

Patterson opened with gratitude towards the conference organizers and shared his connection to GoRuCo, calling it special since it was his first regional conference. He humorously acknowledged his role as the closing speaker, emphasizing his wish to hurry up and allow the audience to enjoy their beer. He introduced himself and his affiliation with Red Hat, where he is part of the ManageIQ team, dedicated to managing containers and virtualization.

The main theme of his talk revolved around optimizing file loading processes in Ruby to improve performance, primarily focusing on the three loading methods in Ruby: load, require, and autoload. He highlighted the following key points:

- File Loading Methods:

- The load method loads files every time it is called, which can lead to errors with uninitialized constants.

- The require method checks if a file is loaded before attempting to load it again, preventing duplicate loading.

- The autoload method loads files when the associated constant is referenced, which can lead to unexpected behavior if not managed properly.

Patterson illustrated the impact of the number of installed gems on performance, sharing an experience where slow response times in IRB were attributed to the accumulation of too many gems. He stated that developers often encounter performance challenges as their gem count increases.

Additionally, he discussed his experiments with measuring load times in their Rails application, which involved over 500 models and numerous controllers, leading to significant boot times.

Patterson emphasized the importance of understanding how Ruby processes these loading mechanisms, indicating that optimizations are necessary as codebases expand. He also underscored the need for developers to analyze and address performance issues systematically rather than rushing to conclusions when faced with errors.

The talk culminated with a motivational message advocating for the Ruby community to collaborate on overcoming performance issues and improving coding practices. Patterson's engaging style combined humor and valuable technical insights, encouraging a thoughtful approach to debugging and performance optimization in Ruby programming.

Overall, Patterson's talk not only provided in-depth technical knowledge but also highlighted the ongoing natural evolution and community efforts required to enhance Ruby's capabilities in code performance.

Closing Keynote: Code Required
Aaron Patterson • June 20, 2015 • Earth

@tenderlove

Talk given at GORUCO 2015: http://goruco.com

GORUCO 2015

00:00:14.780 Hello, everyone! I want to say a big thank you to all the organizers. I'm truly honored to be here. We were talking last night about how I believe GoRuCo is the oldest regional conference, and I don't think anyone has refuted that yet. GoRuCo is also very special to me because it's the first regional conference I ever attended. I'm really happy to be speaking to you today.
00:00:39.030 So thank you for having me here. I want to kick off by saying that the code I’ve broken is indeed broken! This talk is titled 'Code Required'. I have to keep each slide to seven seconds or less because there are many slides. My name is Aaron Patterson; I’m your closing keynote speaker, and I am the only thing standing between you and beer right now, so I’ll try to hurry it along.
00:01:07.229 I also want to thank the organizers for passing out the surveys before I speak. If you haven't filled it out yet, be sure to say nice things about me! I want feedback, but only good feedback. I work for a company called Red Hat, and I’m on the ManageIQ team, which builds an application for managing containers and virtualization. If you have a cloud, we will manage it. My title on the team is 'Hacker Man'.
00:01:31.890 All of our code is open source, and you can actually check it out later. Throughout my talk, I will be referring to different benchmarks that I brought and various things I’m doing and testing. I typically test against our applications, so if you'd like to see the code I'm testing against, you are welcome to check it out.
00:01:52.560 I’m also on the Ruby core team and the Rails core team, and as far as I know, I’m the only person on both teams. I want to express my gratitude again to all of you for being here and to the organizers for having me. I come from Seattle on the West Coast, where we don't have very good traditional New York pizza. I really wanted to go get some, but unfortunately, I didn’t have time yet. Fortunately, Eileen and her husband went out and got some traditional New York pizza for me.
00:02:24.360 My wife is coming later today, and we have some reservations at a really nice Italian restaurant. I'm not sure where it is, maybe in Times Square, it’s called Olive Garden, perhaps you've heard of it. I’d like to share some of the things I’ve learned at the conference so far.
00:02:54.150 First, I learned that we should not hate the player; we should hate the game. I also learned about the concept of 'always be borrowing'. I discovered how to control Hue lights, and let me tell you, that was quite enlightening. I learned about caching (and the dangers of caching) as well as how I should just cache everything all the time. We also talked about Just-in-Time compilers and what they mean for Ruby. I hope that when Ruby gets a Just-in-Time compiler, it can be a bit more classy.
00:04:07.060 From Carrie, I learned about science, and the main takeaway from her talk is that homeopathy works! I also learned about Skynet and pair programming. I want to show you the joys and challenges of pair programming. I do pair programming sometimes, but I’d say teaching feels even harder. This guy works for Shopify—maybe, I’m not sure.
00:05:10.419 All in all, the point I want to make is that we had many fantastic speakers today who delivered incredible information and slides—truly stylish stuff! However, what I want to convey through my talk is to lower your expectations.
00:05:25.640 Mike asked me what my talk was about, and he informed the organizers that my talk is about cats. Yes, indeed! This is my love! I collect cats. Here’s one of my collections and if you want to have a cat like this, I have instructions on how to do it. Anyway, here's a picture that I like, no particular reason, just enjoy it! I also collect strange keyboards, so if you have a fascination for strange keyboards, come talk to me after.
00:05:56.580 Here’s another keyboard that I built myself, and here's another one that my cat thoroughly enjoys. Additionally, my wife and I made holiday cards last December but didn’t get them sent out in time, so I’m just sharing the pictures at all the conferences I attend. Here is one of those cards. Unfortunately, I don’t own the copyright to these images, but I’ll happily complain about that on the boat.
00:06:36.450 I’m an extreme programmer, and I had the chance to meet Kent Beck at RailsConf, which was truly amazing. We actually became fast friends and now, we're collaborating very closely on developing new equipment for doing extreme programming. This is my extreme programming safety gear I’m currently working on at home. Apologies if this is a little silly, but we are now through the entertainment section of this talk!
00:07:24.150 Now we have to get down to the nitty-gritty. Unfortunately, this talk is all technical stuff, and I apologize in advance! You might have noticed something about my slides: The font used is Baskerville, which I chose because I read online that using Baskerville makes content appear more believable.
00:08:30.030 This talk aims to comprehensively cover everything about loading files that you were too afraid to ask about—or maybe you didn’t want to ask about it, but you’re stuck watching me anyway. So welcome! I want to discuss performance issues related to loading code and how we can improve the speed of performance when coding. The reason I got into this topic was that while using IRB, something was off. I would pull it up on my computer as my calculator, but the response time was too slow. Eventually, I found out the reason was because I had so many gems installed!
00:09:51.150 As I investigated, I realized that the solution was simple: don’t install so many gems! However, I was quite annoyed with this suggestion because I wanted IRB to run quickly regardless of how many gems I installed. I just want it to be fast! Nobody wants to un-install gems, I just want Ruby to be quick.
00:10:53.760 Now, looking at Rails and boot time, I’ve noticed that our application at work runs around 12 seconds long due to over 500 models and 83 controllers, totaling about 292,000 lines of code. I measured this by running a simple timing command. Today, I want to delve into how files are actually loaded in Ruby and identify methods to speed up that process.
00:11:52.460 In Ruby, there are different ways to load files: load, require, and autoload. They involve several global variables, notably the load path. Whenever you do a require on a file, Ruby checks the load path to locate it, and you can modify the load path using a parameter.
00:12:47.600 Now, when you call require, if you call it twice for the same file, Ruby will only load that file once. This is managed using the loaded features variable, which keeps track of everything that has already been required. In this way, the loaded features variable acts as a list of already loaded files.
00:13:56.630 The method load is quite straightforward; it will load a file every single time you call it. With Ruby, you can use full path names or relative path names to do this. Also, load has an interesting feature that enables wrapping loaded files in an anonymous module, which could help manage namespacing.
00:14:57.220 However, not all the files you might expect will be wrapped. This behavior could be confusing, as the code might not compile as expected, and you end up with uninitialized constant errors. Therefore, while this sounds clever in theory, it hasn't proven to be very practically useful.
00:15:54.160 Next, let’s explore require. It behaves similarly to load; if you call require twice, it will only load the file once. Require checks the loaded features list to see if it’s already present, ensuring it won't duplicate efforts with previously loaded files. As you can witness, require also returns a boolean that indicates whether a file has been newly loaded or not.
00:16:53.760 On the contrary, autoload is a little more complex. It loads a file only when that constant is actually referenced in the code. Even if you reference a constant multiple times, it will only load the file the first time. Unfortunately, it might lead to unexpected results, potentially resulting in infinite loops if not handled properly.
00:17:50.340 Developers must take care when using autoload since the file gets loaded precisely when you reference the constant. In some cases, this could lead to conflicts or unexpected behaviors when dealing with file names.
00:18:51.110 Now, onto Ruby gems and their association with require. Ruby gems manages to implement require, ensuring that it can locate required files effectively. However, you have to be aware that not loading gems properly can lead to exceptions.
00:19:49.010 If Ruby cannot find a gem, it raises an exception, which we can catch to successfully find the appropriate gem or file the next time it runs. The first time you try to access a gem, it will likely throw an exception, which means you may need a suitable strategy to manage that process.
00:20:45.050 To wrap this up, performance challenges with Ruby can often be pinpointed to gem count and file count. As coding in Ruby grows and gems become more commonplace, it’s crucial to gauge your count and monitor loading time. I’m also investigating the performance characteristics associated with this, leading us to explore optimal configurations.
00:21:43.310 I’ve gathered data through a survey focusing on various types of Ruby installations, including the number of files associated with gems and projects on individual systems. The responses revealed interesting insights into how many gems people tend to use and how they manage file allocations.
00:22:35.220 The average user reported numerous gems and files, indicating a blend of unique setups based on their needs and preferences. Overall, understanding the scale at which users engage with gems is paramount to improving efficiency when loading files.
00:23:52.440 Next, I want to analyze the growth rate of require time against the number of gems activated. A good benchmark is what I would consider both best and worst-case scenarios. In essence, how does our performance change as the load path lengthens with each active gem?
00:24:52.440 Through my tests, I’ve established that the performance grows linearly on average when requiring files as the load path increases. Unfortunately, I observe these issues persist regardless of the file being at the front or the back of the load path.
00:26:03.650 I am currently exploring ways to generate these caches beforehand, improving the speed of require internally while bypassing some of the pitfalls we're encountering with speed in Ruby programming.
00:27:03.930 With principle implementations of caches activated during bundle installations, I believe we can significantly enhance performance as we work towards developing these optimizations. The ideas aim to provide users with the smoothest experience when developing in Ruby.
00:27:58.550 As noted, inconsistencies or exceptions raised from loading processes represent challenging elements we must learn to address collaboratively within the Ruby community to ensure efficient design of our applications moving forward.
00:29:10.160 Now that I’ve hopefully illuminated some value regarding these issues, my closing message is concerning auto-load. A situation arose as I was testing where I encountered what initially seemed like a significant bug—however, it turned out that naming files a certain way can lead to odd conflicts that throw exceptions if not handled properly.
00:30:50.070 Conclusively, as developers, we frequently find ourselves thinking the problem lies within our code instead of considering external factors such as file conflicts. It goes to show that taking time to analyze and contemplate situations correctly can save frustration in the long term.
00:31:33.450 Remember that when you encounter issues, don’t rush to conclusions. Debug properly. Fast solutions might not always follow conventional logic, so always inspect your work carefully.
00:32:18.810 So, let's take our time to understand the intricacies of our code environment and continuously strive for speed improvements in Ruby development!
00:33:13.350 I truly appreciate you all for being here today. My talk may have been a whirlwind, but I hope it sheds light on some core principles in code optimization. Let's keep improving Ruby by being mindful of practices that affect our coding experiences.
00:34:22.640 Thank you all for your time, and here's to better programming practices as we move forward!
Explore all talks recorded at GORUCO 2015
+1