What's up guys? One of the coolest gem that I've seen in a while is bootsnap from Shopify. This gem is actually going to ship with all rails 5.2 applications going forward, it officially got added to the Gemfile even though, of couse, rails 5.2 isn't out yet, you can still use this gem any application in ruby that you want. As long as you're running ruby 2.0 or higher, where it has a bunch of folders in it, and when you require a file like say: open uri, you would have to go through each one of those folders and say: Hey, is there a file called open uri in here? Yes or no? No? Ok, let's try the next one, and it goes through that until it finds open URI or it finds nothing and it throws an error, and that's very slow, because every time that you require a file, which you do a lot, that is going to be a thing where it has to scan that path and keep doing that every time, and so what they do is they patch it so when your application loads, it will check for all of those, and then it will give you that cache, and then it will be able to tell you immediately: Here's open URI whenever you ask for it, or whatever file you're looking for. The other big benefit they do is they cache the result of the ruby bycode compilation, so bycode is actually this intermediary format, so you write ruby and you think of ruby as the code that you write. But, what actually happens is that when you run your ruby code, it takes your ruby, it parses it, it creates bytecode, and then it feeds the bytecode into the virtual machine to actually execute. This is ruby saying: Here's what you wrote, here's what that should actually do, and then it will run that code, and so this actually will cache the bytecode to disk, and then allow you to load that bytecode up without having to reparse and compile your rubycode. If your ruby code never changed, you'll be able to load up the bytecode and run that without doing any of that parsing stuff. This can give a really significant speed improvement for your rails app.
Let's try this out with a GoRails codebase. What I have here is a script that just says
rails runner puts Episode.count in the terminal the episode count, that's it, that's really easy, and all this is really testing is how long does it take to boot the entire app and query the database once. The database time should be pretty consistent, but we should actually see the most amount of work happening on the loading side, so we're going to run this a few times, see how long it takes, get an avarage number, and then we're going to turn on bootsnap and do the same thing and see what our avarage times are after that. Our boot.rb file is going to be the place that we require bootsnap later on, so I'm going to pull that up and we'll uncomment it later, but I want to make sure that it's commented out first.
Here we can say
time ./script.sh, it will run that script, and then give us our time back for that. We'll do this a couple times and see what our avarage time is. The first time might be a little slower, it depends on what's going on in your operating system and things, but you want to get some avarage time. You probably will notice that it just sped up by a second and we didn't do anything. That first time, we're going to ignore because it took a little while just to get everything ready to go and you can see now that our times are more consistent between 4.7 and 4.8. Maybe 4.75 or 4.8 is our avarage time here, but it does take a little bit of time to boot our app. Close to five seconds. If we turn on the required bootsnap, the first time this goes, it's going to actually create files in your temp cache directory for the load path cache, and the compile cache. I've already run this of course, so these files already exist, and you'll see that now when we run this script, this is going to take a lot less time. Under three seconds now, which means that it was about two seconds faster, and if we do this some more, we should see that it avarages out, I think it should be around 2.2, 2.3. That's what I was getting before. 2.2, 2.3 is significantly faster than our 4.7, 4.8 that we were getting before. You could actually write, if we wanted to, a script to do this like 100 times, take the avarage times and then you have a really good idea of how much it improves things, because you're taking 100 runs of each one. That would take a little bit too long for a screencast, but as you can see here, it's already a big enough percentage change that it definitely is helping. If you just add bootsnap to your rails app, you will get a speed increase for running tests, for running your rails servers, for booting up anything that you would possibly want to do that needs to load lots of things, and that's it. You install the gem and you set it up and you're good to go, so if you want to learn anything more about how this works internally. I know I just talked about it at a high level, but if you would like to learn about any of those details, how the load path works, or compilation caching, go for it. This talks a lot about it, you can even dive into the extention bootsnap folder and look at the C code for this. Now or course, this only works on Mac right now and Linux, so maybe if you're really interested in Windows and C, you could add something like this for Windows, which I'm sure they would love to see. Right now, it's just Mac and Linux and it does a really good job of that, so you can read through this code, kind of get an idea of how it would work to build a C extention, and then you can see how this works internally to do those caches.
That's about it for this episode, and as you can tell, 25 minutes ago, they just came out with version 1.1.3 it seems while I was recording, so that's awesome, they're heavily working on this and trying to make it faster and better and everything like that. I've been using this in production, so you shouldn't have any troubles. They've been using it at Shopify, so everything you see here should be pretty solid, but yeah. Take a look at this, and if anybody tells you: "Adding gems to the Gemfile is going to slow your application down" You can now prove them wrong and show them bootsnap and just show them how much faster it is. Anyways, I will talk to you guys in the next episode. Peace
Hey Chris! This is really helping booting my apps faster! Thanks so much!
I implemented this and my memory consumption on Heroku went up by 40Mb. The truth is I wonder if I even need this on a Heroku production environment. Is it advisable to run this in development only?
require 'bootsnap/setup' if Rails.env.development?
Yeah, it's encouraged for production, because production will boot faster. The extra RAM usage is going to come from the cache it because that's how it boots faster. It's trading RAM for speed.
Certain memory constrained environments, like Heroku typically is, may not be a great place to do this if you're struggling to keep your app's memory usage down. Otherwise, you should basically use this all the time.
Hi Masud. Recently I moved from AWS to Heroku and that was the best decision I made. Everything worked out-of-the-box. The application itself, solr, the database. Everything was reeeally easy to set up.
I didn't check Digital Ocean though. Could you elaborate on why Digital Ocean was the best decision for you? Thanks!