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!