What's up guys? This episode on GoRails, we're going to talk about the performance on gorails.com. This is a question that came up on the forums recently about, you know, what are the tactics that I use to make gorails.com fast, and by any measure, I don't think GoRails is very fast. It's definitely faster than your average site, but that's definitely not in the 150 ms or less to glass measurement, which is the measurement used for saying: If you're 150 ms or less, generally that's going to appear to human beings instantaneous. GoRails isn't quite that fast but it's pretty fast, so we're going to talk about all of the different things that come into play to make GoRails as fast as it is, lots of improvements to make but we're going to talk about the ones that I've done so far.
So step number one is to simplify the amount of queries that you do. Keep your pages as simple as you can, that will help improve the performance at the database level. Now, that is even tricky on it's own, because database queries will show up with ActiveRecord saying: Well, this ran and it only took 3 ms. Well, it's not quite the case, because ActiveRecord actually has to take those results, put them in memory, then it has to convert all of that stuff into ActiveRecord objects, then you have to convert that into html and so on. It's a lot more work than the performance numbers of 3 ms of query time show in your logs, so you have to be careful with that, and that means that doing fragment caching comes into play significantly for performance when you're generating html server side. So when you're fragment caching, you want to make sure one of these records like this is cached into rails cache, but you also want to make sure that the rails cache is configured to save either until like redis or memcached, and the reason for that is because with those, you're saving the cached memory, so it's very quick to access, if you use the default cache, actually you have to write to your hard drive SSD, now SSDs are a lot quicker but they´re not still anywhere near as fast to and from memory, so if you can figure your rails cache to point to one of those two external services, you´re going to get a speed improvement for that, which is what I do. Now to take your fragment caching to another level, you can do rush, which is a recent feature of rails that basecamp talks a lot about, and it's really the concept of recent questions on the dashboard here, this is a section of the five most recent questions, we can cache each one of those in a fragment cache, but we can also encompass into one fragment cache, and then bust the larger cache when there's a new question, or one of the old ones gets updated. This is really nifty because it allows you to say: Well we're only going to access the class once for this entire chunk, instead of accessing the cache five times or more for every one of those questions. So that saves a number of network calls between you and redis o you and memcached from five to one, so that's pretty fantastic as well. That is another layer of reducing the number of queries that you're doing in order to get better performance when you're caching even.
Transcript written by Miguel
Hey Pete, this usually happens from one of two things:
1. You're using a third party library (like Segment.io for example) that isn't compatible with Turbolinks events by default. These usually require some tweaking in order to make compatible. It all depends on the library but there are usually ways to do it. You can google for that library + turbolinks and see if anyone else has made it work, or if you can tweak it yourself.
2. Sometimes it can just be a simple setup issue if your JS is running incorrectly. Maybe you need the jQuery.turbolinks adapter, or just to modify your code slightly to allow running on multiple pages.
It all kinda depends on your code and the issues you're experiencing. They can be kinda hard to track down so the easy solution is to turn off turbolinks for those links in the meantime if you can figure it out. I don't think there's anything wrong with that so you can figure it out later.
Hey Chris, thanks for getting back to me.
Well mostly the problem is with external libraries to be honest. Guess data-no-turbolink seems easier than trying to find a solution each time. But maybe its high time i do that.
Great insight! Though now I'm really hoping you'll do another video on how to implement and get the best out of Turbolinks. Few resources out there and you did a good job with the marketing :D
I definitely will. I also need to learn some around Swift and Android so that I can make some example apps using the Turbolinks adapters. That might mean we'll have a GoRails mobile app at some point. :)
Mostly because I'd rather spend most of my time doing the heavy lifting in Rails rather than JS. If you built your Rails frontend in React already, React native is the way to go. Since I'm using Turbolinks already and because I don't have any complex JS widgets on the frontend to need React, the Turbolinks adapters are the best solution for me. React could just as easily fill the same gaps, just fits well for me.
With Turbolinks on mobile, you get a web view that embeds the Rails site just like you would have in your browser, but you can override link clicks with native code. So all the stuff you see on mobile is just as if you were viewing it in the browser. It's a hybrid app because of the webview, but easily intercepts those things to do native Swift or whatever. Turbolinks would only need the server to return HTML and so you don't really need to build an API.
React Native is somewhat similar in that you're still sharing the same app code with the main website, but you will have to build an API to make React work, and you'll need to do some extra work to serve up the HTML as well.
Give their readme a look on the new iOS adapter. It might help wrap your head around it a bit. https://github.com/turbolin...
Basically your mobile app just ends up primarily being a WebView (webkit browser full screen) and it let's you set the website. This is similar to things like PhoneGap in the past, except that the code is all just your public website meaning you can update your mobile app at any time by deploying your website again. Pretty slick! I'm not sure if React Native lets you do things like that.
Another suggestion is a non-rails issue, but fundamental nonetheless: focus on the database queries themselves. A great suggestion I have held dear over the years is to ask "what are the critical queries an application may have?" (the most frequent one, the most valuable, the most calculation intense...) On that basis, with a knowledge of how databases index, one can often find a data structure that is more efficient than another (conception over optimisation). Large test data sets for different data structures allow to validate design choices. To me, that is the core of the onion...
Chris, any chance you could go into detail about how to set up nginx and passenger to properly utilize the resources of your server? I follow your guides when installing so no fine tuning is ever done to my servers. Also would love to see how to set up redis for caching.
Thanks Chris. I would love to see how you make improvements on all the external API calls for getting data from different services.
I would love to watch a serie , instead of a bunch of randoms episodes, something like laracasts but for rails..... A lot of people will pay for that
I've been realizing I need to make that transition soon anyways just because there are way too many screencasts to keep track of at this point. :)
I'll probably be migrating to a bunch of small series over the next few weeks!
Question, maybe to clarify some things, if you can, please answer, thanks.
Why did you choose digitalocean over heroku?
PD: Im thinking about changing to digitalocean because in heroku every add-on in production mode is paid, and if you have few your are going to paid 3x times more than having a digitalocean($20). But i not sure if i'll make the right things in digitalocean.
I chose DO because I like running my own servers and its significantly cheaper than running on Heroku for personal or small business projects. You'll have to do a lot more work, but it can be fun so long as you make sure you have backups and all that in place.