Ruby core team и Rails core team. Senior Software engineer в маленьком стартапе, который называется GitHubView the profile
About the talk
RailsConf 2019 - Closing Keynote by Aaron Patterson
Hi. Oh, hi. Thanks. Thank you Marty. I'm so excited that Ruby Central has announced that the rails conference going to be held in Seattle next year my hometown. So I don't have to drive the 3 hours to Floral assistant. All right. Hold on a sec. My my computer fell asleep here. Okay, here we go. Here we go. Here we go. Okay, so hot. Why don't we have one that one thing? I got to take care of her someone in the audience name to Devin. He's down here at his he brought this turtle with him if his daughter is turtle and he asked me to take a photo of it in front of all of you. So I'm going
to do that now but I would like you all to clap for the turtle because of the turtles biggest audience ever. So please Alright, thank you. Thank you. The next next thing. Is that oh crap, hold on. Using up all my time. Hold on. I got to get a cell. I'm trying to remember all of these. Okay now it's my turn to all right everybody. Yay. Okay, I heard that. There's also a bingo thing going around like a bingo card bingo card thing going around and I I believe it's I believe it's unauthorized but I'm going to read it. So I'm going to read out a few of them here and see if we can get a bingo
going. Let's see common backgrounds grateful bunch. I was born into the software community Through the grace of open-source a land where milk and honey flow Eternal and you can go to anything goes yet. No not well continue. I built I built some more of these into my talk. So hopefully you can get Thank you for laughing Evan. I don't know where you are. I can hear you laughing though. Alright, so every year it seems that it seems like David gives a very first key out of of rails, and I
end up giving the last keynote and rails, and typically my strategy for the stock is essentially to get on stage and make fun of David in his Danish person. But the problem is like I was thinking back to myself like okay, I I do this I do this every single year, but the issue is that doesn't scale. Any bingos yet? I want to declare I want to declare that this year is a jubilee year. The year, I will not make fun of David in my Tina. So I like you. All the things that I am not doing. Okay,
so this year this year I decided to do something different. I decided to put all of my thoughts down on paper. Rather than standing around here rambling at you. bit more thought-provoking So I have written a script. I'm going to read it to you. Hold on. shabang / user flash.bin / Ruby death FIB parentheses in parentheses If n is less than 3. 1 elf in parentheses + - 1 close parentheses + FIB open parentheses 10 minus to close parentheses. end end guess that was my Ruby script. So actually I make
fun of David a lot on stage, but I actually really like him and admire him the other day. I went I met with him at the speakers there before the conference and I actually got him to sign a copy of his book for me. And this is this is me getting a signature as a very excited. So yes, I am calling this talk of but at what cost Thank you Eileen. She gave me the title. Yes. My name is Aaron Patterson. I'm very I'm really really happy that I could be here in Minneapolis to
give a talk to you to all of you you could say is that I'm really happy to be presenting to you live from here. I know there's like six people in the audience to get this a joke, but it's it's really yes. It's important to me those six people are very important to have a cat. His name is garbage garbage puff-puff thunderhorse. I'm so sorry. Another picture of him extremely extremely flat face, which I think is extremely adorable that also means that he can't go outside. Otherwise, I'll probably
die cuz there's no way he can defend himself is my other my other cat. Her name is Seatac Airport Facebook YouTube Instagram Snapchat Paris I should have thought of this in advance. I apologize. She likes to stick her tongue out alot and this is another photo of her to sleeps next to me while I'm working out. How much is she sleeping like how deep is this sleep? So I decided to Sorry, I mean honestly, I kind of like a kind of makes me mad cuz I'm sitting there working and she's like sleeping right there and I'm like, why am I
working so hard? Anyway, I I I brought stickers of my cat both of them. So if you would like a sticker of my cat come say hello to me afterwards. I like to bring stickers because I know that people are shy and don't know what to say to me. So you can ask for a sticker If you don't know what to say. Also I am into Ruby programming. I also like taking selfies and I am a member of the Puget Sound mycological Society. I'm a mushroom hunter it is true. So anyway, my my name online is tender love if you don't recognize
me in person. This is my avatar as what I look like online. I was looking through my Twitter bio like the the information on Twitter so you can like look at the advertisement information like what it is that they advertise to you. And one of the sections in there is like it is what are you known for? So so what are you known for online and it tells you and I I I was very amused at what I have known for I am known for software development and other And I feel like other maybe puns and if that's the
case, then I was like really nailed the other category, but I'm not I'm not totally quite sure a story of how I made I accidentally made Twitter completely useless for myself. I typically use Twitter for just telling like bad jokes online pretty much and like sometimes I'll tweet at a thing or two, but typically it's just not bad jokes that are super good joke. I only tell super good jokes online. Anyway, I'm pretty sure Twitter like Twitter can only get users to have basically one of two feelings and that
is either anger or face pain and I typically like I prefer to generate facepalm. So that makes me really happy eyesight elk hunt online and I I like to imagine that there's somebody out there reading that just going like I sit back and I just go. Yeah, anyways, so like people started responding to my puns with just just my name. It was just the errand and like so every time I tweet upon this is like all the responses at all of my mentions just say my name and then it's gotten to the point where like when
other people is my friends say a pun. Then people will respond to them with my name. actually One of the one of the speakers here, will he put together a bot that all it does is a certain percentage of my tweets just responses and was Aaron. I've got I've got 50 minutes left. So I think I'll I'll tell this story but will like this bot has been replying to me for like a year and I didn't I didn't know who it written it. Nobody told me who wrote the spot. I was at a conference recently. Keep Ruby weird. Where will was giving? Yes
keep Ruby weird. Where will was giving a presentation. I was the MC at the at the conference and Will was talking about all this crazy stuff that he did and one of the things we talked about he announced at this conference where I was MC that he is the one that wrote the spot and I'm pretty sure I was just like what Anyway, I want to see I want to see her one more response to me, which this is probably the most high-effort Aaron response that I've seen so far and I want to I want to share it with you this okay?
Eric anyway, so this I think this is the best of the highest ever won a response to me you so far but that's only made my mentions approximately 54% useless until until one fateful day March 14th, 2019. I made a very huge mistake and that was what I tweeted this. I am trying to respond to things with but at what cost more frequently and of course the very first response was And now the other 46% of my mentions are essentially this. Fortunately, nobody yet has build a but at what cost but but but my Twitter is 100% useless at this point. I mean, I think I
think you could make it like you can make a strong argument. The Twitter was already useless, but you know what I'm saying here right like you get what I'm saying? Unfortunately, I've gone from being the the one who imposes facepalms. I'm no longer the face Palmer. I am now the facepalm me to kind of unfortunate but we had their there is an algorithm to this and essentially the the response algorithm is if I say something that's a pun you respond with Aaron and if I say something that is not upon you respond with but at what cost
And I will I would like to do that here today with all of you. So let's let's practice doing this. So let's do this. So I'm going to say something and you have to respond with the correct response. Okay, people keep telling me I should try Docker, but I'm not a fan of business casual. I'm glad they're ending Game of Thrones instead of just letting it drag on. I love that one. I love speaking of rails, and I'm so happy that I could be here today. Okay,
thanks. So I work for a company at tiny startup called GitHub. I'm a software engineer at this company. You can say this is my active job. 45 minutes of this left last year last year, but Good Hope was acquired by us a late stage startup / lifestyle business faced in Redmond. The question was but at what cost and I will tell you what the I'll tell you what the answer is. Many people so many people have asked me like as it has anything changed and I can tell you that the only thing that's really changed is I changed my
desktop background and I changed it to a picture of Redmond witches if you've never been threatened before it looks like that is really beautiful. Anyways, please now pay attention to the obligatory GitHub. We are hiring slide now. I think that most companies that this conference have we are hiring flies, but I'm pretty sure that GitHub can provide something that no other company can and that's essentially access to all of my unreleased puns. The cost as you get to Phase 5 everyday.
Here's one of my one of my coworker is tweeting. She she quoted me from. This is from Slack. I have to admit one of my most favorite things is that I will type up a l type of pain into slack and then it's just the best like it'll just sit there and I'll see you like typing. I meant no typing and I'm typing no type. In 5 minutes later. Somebody says something else completely unrelated. I'm like I did my work here is done. So if you would like to come work with me and ends and also facepalm, then you can go to this website or scan this QR code or come talk to me later.
Anyway, I'm also on the Ruby Cora team, which is a team responsible for developing the Ruby language. I recently learned that this is my actually might 10 Sierra. So it'll be my 10th anniversary in October of being on the Ruby Cora team, which is amazing. It's my most on the rails core team and I decided to research how long I've been doing that. I've been on the core team since 2011, but my first come it was in 2009. So I was actually about 10 years ago now and Jeremy is the one that merged it. So thank you Jeremy. I really appreciate it. Now. I'm not saying this to like
toot my own horn or boast about how long you know, my compliments or whatever. But what I want to talk about is how long I've been in the Ruby community and why I stayed for so long and the reason is that I just I love Ruby a lot. I love Language, I've been doing development work since 1999 and I got into Ruby programming on 2005 because some of my co-workers went to the nofluffjuststuff conference were Dave Thomas was giving a talk about Ruby they brought it back to her office and showed it to me and I really enjoyed it at the time in 2005. I was a reluctant Java programmer
and programming and Ruby felt like a breath of fresh air to me. The language was so easy. Everything just worked. It worked the way I thought it might work when I made a mistake. It was easy to tell why I like the the exceptions word clear the basic patterns of the language were very easy to pick up. So it required much less mental overhead then say Java so I didn't have to think about as much stuff when I was programming that I can just focus on getting my job done is also nice if there was no boilerplate code and to give you an idea of what it was like to write Java back
then this is this is an example on the left his job. Right is Ruby and they're essentially doing the same thing, which is just napping over a list trying to convert a list of strings into a list of integers. Now, I don't think the Java example here actually works because when you do a person that actually returns just an in primitive rather than object and you can't push that on to this Ray so you have to think about stuff not everything is an object. Can you have to think about that stuff? And that's a type of mental overhead that I'm talking about that Ruby doesn't have so
I want to tell you a story about my very first Ruby program my first serious review program in 2005. I want to see Lord of the Rings. So it was the third Lord of the Rings movie coming out and it wasn't there was going to be all three Lord of the Rings movies all show no one day and they were showing it a day early and that was my birthday. So I really wanted to go to this I went into work and I tried to purchase the the tickets online. I just crashed and I tried a few times in the website kept crashing. So I decided okay. I'll write a ruby program to do this. Like I said at
the time I was a Java developer in our project took about like 10 minutes to compile. So what I would do is during the compilation time, I would write my Ruby program to go buy these go buy these movie tickets for me and I even put my credit card information into this trip. Like I literally put my credit card number in a text file and saved it on my hard truck is not encrypted program with the program would make a request and try to purchase the tickets for me. And I knew what the failure state was. Like, I knew
that the website was failing and what I would do is okay, if the website fails, I'll just reach fry but I don't know what the success case was. So my thought was all right. Well, it's probably going to be a failure but a different type of failure. So what I'll do is just log a message and then retry right? search so it never ended it was an infinite Loop. I figured I would do it but at what cost was a very good that is a very good question and we will get to that.
Saw the program was running and I forgot about it and was going about my job and then later on. I noticed that the output of changed so I killed the program and it changed quite a while ago. So I went to the website. I tried to go through the process and I realize that it actually been succeeding a whole bunch of times. So I called the credit card company. Like I had a mini panic attack and I called the credit card company and ask them like one of the most Shady questions. You can possibly ask. I'm like how many times has my credit card been charged
today? I feel like that's something you should know, but I didn't. Credit card person to tell you that your car has been charged once for like 40 bucks something so like great. I only had only one transaction crazy, but I wasn't sure whether or not actually got the tickets because the website and kept failing so I called the ticketing company the ticketing company like I told him I information I said, hey, I've been trying to buy movie tickets and I'm not sure it like the credit card companies. I was charged did I actually get me movie
tickets? They looked at my info and the guy says well, yeah, I bought two tickets, but it looks like we've tried to charge your credit card hundreds of times. And I was like, oh, yeah, it just kept hitting like Refresh on the website. I don't know. Anyway, the moral of the story is never right infinite loops. Make sure there's some way for his exit anyway around the same time. I discovered rails like that that time of that time was when do you take to release the the mega block in 15 minutes
video and I I tried out rails and I fell in love with it had exactly the same the same features as Ruby. It was very easy to use everything just worked. I work the way I thought of wood I could build a website really quickly. I could focus on my my actual job and there was no boilerplate boilerplate code, but it wasn't just the specific traits about the language and framework that made me stick with it for so long. It was that there was a kind of community that values this sort of stuff is this type of thing like we want the computer to do the work for us this
this type of value is the type of values that I want my community to have in the people that I work with the have its situation. I would like to be working under every day. So I decided at that time I have to I have to become a rails programmer. I must write rails for my job. This is an actual photo of me from 2006 through their I have much less gray hair then anyway, I knew I had to become a rails developer, but at the time nobody was hiring rails developers. However, I I I knew I had to become one and I know what you're asking yourself.
May I know I had to prompt that one there are so many other unprompted. Anyway, I'll tell you exactly what that cost was minus 25% of my salary. So I took a 25% pay cut to get my first job programming rails. I was in a place where I was more happy and I knew I wanted to be more involved with Ruby in the rails Community because I wanted there to be more companies that had reeled applications. I wanted there to be more competition so I can find a better
job so I can get a better salary so I could work around other people who share the same values I did. I wanted more people who are in the community as well people who also share the same values and this is this is the type of stuff that kept me motivated. Now I speak in a lot of conferences and frequently when I go to conferences people come up to me and say, you know, thank you for the work that you've gone on at what size thank you for the work. You've done a ruby and rails knows things and the story here is essentially a long way a really long way for me to get around to saying
actually awesome. Thanks to you because you are all the ones that are building companies using rails, you're all you're the ones programming and Ruby you're the ones creating demand. You're the ones that are enabling me to actually be a What do Ruby as my day job, so if it weren't for you, I wouldn't be able to get a job writing the language and framework that I love so much, so I want to say thank you to you. The question is but at what cost I will tell you. Let me give you the answer. The answer is endgame spoilers.
I'm going to spoil endgame. This is my end game Keyboard. And I know you're asking is I will never buy another keyboard of the best keyboard in the world, and I know you're going to ask me about it. I'll tell you the cost Acosta me. She's everything. Seriously, if you don't get it don't don't get into mechanical keyboards because they are extremely expensive Game of Thrones. I mean, I don't even watch like I don't even watch Game of Thrones so I don't really care whether or not it gets spoiled for all of you. So I'm just going to let you just
going to let you all know that Dumbledore die. I'm just kidding. I have never seen Star Wars. Now for the technical for snow by freezing to his ears just a little bit. You were all here to actually get some get some value out of this conference thing. The last hour free do something productive cool performance tips that these are performance steps that you can use on any Ruby application a rails application and they don't work for either of those the first the
first tip is that a meeting parentheses is actually faster than having parentheses. And if you don't believe me that this is what I'm talking about it so I prefer the style on the right versus the spy on the left these two piece silicone have exactly the same functionality just want to have parentheses in the other one does not. Okay. Now I can tell you that the one without parentheses actually runs faster than the one with parentheses in this is actually very easy to into it. Like I will I will give you a logical reason why that is we've all
heard this adage that no code is faster than no code. It must be faster. If you don't believe me here use this command Ruby that's why is the flag that you can give to Ruby that will output the state of the Purser. Well, it's parsing some code so we can actually see how many transitions the state machine makes wild parsing Ruby code. And if we pipe that to WC. Shall we can tell how many states the price I had to go through all parts in it and it turns out if you have
parentheses, it has to go through more States so clearly it must be faster. Sorry, I'm just pushing my own coding style and all of your the next speed Performance Tuning Pro tip and that is a single quotes or two times faster than double quote. At what cost? I'm just I'm making the entire reals, volumes mad at me. It's fine. I don't mind. I'll tell you why this and double quote and the reason is because you don't have to hit the shift key. How much time is saved you right now like it? Alright, so I'll give you an actual and actual performance tip for a real 6th,
David and talk about real 6 in his keynote and I am going to now and this is like one of my favorite things. It's a very very small thing that's in rails 6, but it's one of my most favorite things implemented so far and that is a if you take a look at the output in rails fix the upgrade and look at the output. There is a new thing in the output which shows the actual number of allocations that any particular template is made so this is going to ride rails application today. I didn't want to just roll you the entire time.
So there is something that is actually useful accounts are actually cumulative. So it's the number of a locations in South + children. If you're wondering what that output is, like kind of similar to the time so you can see those in the logs. So I want to talk a little bit about getting off at rail or trails at GitHub. I'm on the Ruby architect of team with Eileen RT mostly works on open source libraries Ruby and rails included. We focus on extracting parts of our application that are not courts of the business and things that we could open
source and push back Upstream today want to talk about two of the things that we are working on and currently trying to get up streaming that's template free compilation and Method name generation template free compilation is essentially a technique where we say, we compiled all e r b templates are all of our view templates as the application boots rather than lazily compiling them which is what rails does today message name generation is a little bit harder to explain. This is a this is a compile time optimization. I'm not going to explain it too much in detail will get
into it later in the in the talk. Because I think we need to build a little bit of background before we actually get to this and in order to do that. We're going to build a temple renderer. It was but it will cause the cost of your saying it didn't we all know that and for those of you that don't know this rails is MPC the way it works is when I request comes in the request was handled by a controller the controller gets data from the model passes that due to the views of you goes back to the controller and we
send that back as a response at one point in my career. I actually work for a company that works on a system for blocking pop-ups. I was a pop-up blocking company and there we developed a system that was actually known as a model view controller. at your time I'm sorry. Anyway, so we're going to be looking at this part of it this heart of rails. We're going to look at action view here. I typically talk about active record but I'm going on record is talking about action view.
Sorry, as I said, we're going to talk about actions do not confuse responsibilities for finding templates compiling Templeton executing views. So we'll talk a little bit about you templates The View templates are implemented was a temp living language called the RB this is this is specific to rails but you are be like this you could be we could be talking about him or any other templing language really we're going to use the RV in these examples of language was developed by inseki. It's part of the eye Ruby standard library and ARB
templates look like this. I'm sure you've seen them all the four and the way that you actually compiled and use these as with code like this you basically just this example Heroes Compiles the template that second line their print out the source of the template all all the RB compiler does is take your view as inputs and translate that into Ruby code and then we evaluate the Ruby code and print out the result still if we look at the compiled values, this is what this is what the actual kempot the generator Ruby will look like now if we use this code is not going to work in the
reason it won't work is because we don't have a renderform method or link to Method. So if we Implement some very simple versions of those we can actually compile and run the CRP template and the output will look like this so we can make it work. Now there are two tags that we looked at in here and we're going to wear to talk about a strange and not fun feature and challenge of this this template language. Here are the things that we saw the first one evaluate some code and print it out and the other one it just evaluate some code. So it doesn't print out the return
value of that. So one common thing we doing rails as we like to capture the value of a block in the in helper. So you maybe was form for do or something like that. We want to capture the the block output. So, for example, we have a we have a temple that looks like this. Now if we execute this code, what is the alpha going to be? Is it going to be a hello first? Hello in the middle or are we going to get an error? Well, the answer is we actually get a syntax error and I'm going to show you why the reason is because when capture this this template gets translated into Ruby
RB doesn't know that do belongs to end. So it just does a unintelligent a cat red just translates those. So we translate over the capture do and try to print that out and then the end is just evaluated as normal code and text her this won't work. So how does rails deal with this? Cuz clearly we we have to use this in our in our temples today the way it works is in the ER beat compiler you you don't need to read this code essentially. All it does is ask and Ruby code looking for things that could be blocks and then treat them treat them that way. So
that's how it can detect whether or not do an end of along together. We got a little bit down the rabbit hole here. So I think we're going to step back a little bit. They're actually different flavors of BRB. There's the original gyro be that comes that ships is Ruby. Then there is Aruba switches what rails used for a very long time so real started out with you or be when we move to Aruba. So it was faster than trb. Now. We're on Touhy Ruby, which of the nother implementation he's all essentially do exactly the same thing like you you can upgrade rails and never know that you switch
between any of them. Just that one is more performance the other so e Ruby is the current one that we use and it is the most performant. So let's talk a little bit about your performance this again. This isn't real specific or Temple language specific, but we are going to use the RV in these examples. So let's take a look at rendering speed here. This is just some code that renders a template and if we time it in our output is about we're able to render about 27,000. Templates for second and that's pretty good, but we can actually do better than that because our Benchmark what it was
doing was actually compiling the compiling the European evaluating the RV and executing it every single time and we can catch some of that. So in this example, we changed it. So it's that we cashed compilation so it rather than compiling and every time we'll just compiled at once and then evaluated each time and if we compare this to the original version, it's about two times faster is who are able to were able to render about 63,000 templates for second. So this is good much faster so we can do it we can do even better than that though. We can say let's only evaluate once so
rather than calling eval every single time. What we can do is to find a method. So in this example, what we'll do is we take the source of the template. We actually use that source of the template to define a method If we look at the method output, the method will look like or if we run it run this example using the method that declared method runs about 52 is 52 times faster than the original so we're able to execute this template about 1.4 million times for second. Let's take a look at method definition a little bit more in-depth. So this is a very
simplified version of that Benchmark. But essentially what we have is the template Source here in order to generate a method with this. We just evaluated we compile The Source, we calculate a method name for it and then call eval to define the method and then we just essentially send a message to all that stuff before we only do that once So this is what the compiled source of the method looks like. It's just the source that the ER be template Temple of handleit Handler generated. So we just take the output from
the from the RV and to find a method with that as a source. So we can say generally that templates are translated into methods. This is exactly what real goes in your applications. All of your templates are actually generated into a method and evaluated on to a particular class. So this is a rails we given this knowledge if we have a temple that looks like this we can actually print out all of the methods that are defined. So if you put this template into your application and then look at the output in the logs, you'll see a bunch of methods that look like this and these are the
generated methods. These are the ones that these are the message that are generated from your templates. Down with this information. We we can also start calculating the size of these methods as well so we can calculate how much memory each of these templates are using. You can do that. Like this is an example. We just get the method and then we can check the size of the method. So let's take a look at Temple handling and rails up until this point everything we've seen is just been Ruby standard Library. None of this was specific Trails, but a build the foundation for understanding some of
the behaviors of rails application go from here. I want to talk a bit more specific about rails. So first, let's take a look at instance variable visibility. Now, these are two separate templates. But both of them are able to see the same instance variable. The question is why is this and if we think about the way that temples are compiled those being turned into a method and then put on to a class the answer is actually pretty simple if we expand these out will see that these two methods are on the same class. And of course methadone the same class can they access instance variables on
that class? It is just a regular class in those are just regular methods. They just happened to be your templates. so one thing that's kind of bothersome about this is it means that you can't really tell which templates is it since you can't see this class. You can't tell which templates Define which instance variable. So one thing that we actually do it work is we don't allow instance variables in our templates. So don't use instance variables in your temples. Now I'm not saying don't run out and change your entire application to remove all these it just kind of
confusing cuz you don't know who to find what ended in what order they need to be run so you can actually quote me on this don't use instance variables new template school. Not much. Really? I think it's do it if you want I just wouldn't Another instance here is a we already complained about this another issue with this is local variables. So we typically pass local variables to Temple. It's in the way that you pass local variables to Tim Hortons with cold like this. Sure. You've seen it.
We just passed the hatch there and in this particular example, I were passing a local variable with the name. The local is named named name and the value is gorby, although we have kind of a problem if we think about the way that these templates are compiled and evaluated we know that they're turned into methods. But if we take this as a template and this template content and turn it into it, like look at the source for that. Will see that it calls this name here, but the generated method is a method called there is a method call inside there. We don't have the name for
amateur past to that message. So how do we get those? How do we get the locals passed into a message like that the way the rails deals with this is that we Define I Preamble that contains the locals in it. So if you look at the if you look at the Methodist generator the code for the the best generator to it will actually contain this Preamble up at the top that defines the local name. So take set hash into finds it. So unfortunately this leads to a couple different problems and that is let's look at this. Let's look at this example here on the right is our constant.
Template on the left is the temple if it's trying to render the content template, if you look at the content template, can you tell me is name a local variable or is it a method call? And unfortunately, it depends on the context in this first case. It's a local variable the way that it's being rendered but in the second case, it's actually method call. So the second case will get a method missing error where the first case will actually print out the name Corby now, unfortunately, this means that we can't compile Templeton Advance because we don't have the contacts with it
within which the temperature is supposed to be compiled. We don't know what the local variables are supposed to be for particular template. Now. It's going to lead to another problem to which is that we can accidentally compiled a template to many times. So here's another example where we have to templates there or to render calls or both rain during the same template, but they're passing in different local patches. And that means that we have to Define multiple Preamble. So we end up defining and a method for this template twice. And it's a sad because we have to use extra memory for these
templates. And also the the friend local is never used and I like friends. Aaron you may be saying yourself tear in this is nice. But what should I do about this my Pro tip for you today in your rails applications now is to make sure that you always pass the same locals the individual templates trying to make sure that you're consistent passing in passing the shape of that Local Pass to each template not to ensure that your temples are compiled multiple times. So let's take a look at the rendering function to the rendering function at a very high level does things
with Rangers templates. It's responsible for finding a template compiling templates calculating a method named and calling the actual method and if we break this down into a diagram like a logic diagram to look something like this where we always we have to find a template we check to see whether or not the temple is compiled. Sometimes we have to compile the template and then figure out a method named and then we call them nothing. I want to talk a little bit about finding a mess of finding a template we've seen most of the other pieces of the puzzle for rendering things and calling methods.
But let's look at finding files to do that. I built a little test application now, unfortunately when we render templates the template rendering depends on the requested format and let me show you show you an example of what that means. So here we have a user's controller and it renders an index template and we have two templates are in HTML template and an XML template the contents of each of those templates when I was just texting all the other ones are so users and here's a table breaking down the responses for particular requests. So if we request with XML will get
the XML template if we curl with nothing will get the HTML template if we curl with HTML, of course we get the HTML template. So to know which template needs to be compiled. We need to know the requested format. This means that our cats can use or something like local variables. We need in order to figure out the temple. We need to know local variables. We need to know the format the Locale the variant. Now some of these things we could know in advance. So be nice. If we did then we could actually start pre compiling these templates. So strange. I want to talk a little bit about
a strange Ranger Behavior as well here in order to demonstrate this I made a little sample application as well. Here is our our users controller. I've added two temples one is a ping and the other one is an XML. So we have the same controller with the views are slightly different. So here is what are templates look like we have one template that all it does is it's our main index template. It renders my template and then the pain template just says, I guess this is a ping and the XML template says XML is cool. Okay. So let's do the same request same request
thing that we did before same request table and the interesting thing is that if we request XML will will get an error cuz there was no XML template if we request text HTML we get an error because there was no HTML template if we requested the browser we get the same thing, but if we do a bear curl for some reason it renders the Ping. That is neat. I think here is a browser error just to prove I did it. So yes, this is our outstanding one for some reason the bear Coral render a ping and I
personally think that is a bad behavior. So what does Amy and what this means is if we look at this particular template, we can't predict what this call is going to do. So which Temple is render. We don't know. Okay, I'm going to make it a little more annoying respond to the controller. We change it just a little bit before we had it before we had to Bear render. And now we're going to do a respond to with a still going to do exactly the same test. We did before the same crawls and see what the response is look like in this case. It's completely
consistent. We are is across-the-board even a bear crawl cuz it's an error that we're missing an HTML parcel what this means is that that render call is actually context-dependent when we call this render here. It's not just dependent just on the format that's being passed by the request. It's also depended upon the context with it within which is being called. So this render is impacted by the rent that render above it or this render above it as well. It means we can't look at this template and know what it's going to do without having a particular context means these temples are not
context-free. Right. So I've been I've been harping a lot on prediction inconsistency and I want to talk a little bit with regards to the temple run during going to talk a little bit about why the reason is because we're going to go back to the diagram and after doing performance testing on her system, we found that we found a testing whether or not a a temple with compiled is rather cheap that calling calling a method is rather cheap, but bottleneck the bottleneck here is actually for calculating the Cass keys. So these things are cheap, but cat calculating The Cask.
He's actually very expensive. So it'd be nice if we didn't have to calculate that cash key and unfortunately, when we look at this, we don't know what it's going to render so we can't calculate the cache key in advance. So what would be nice is if we knew what this is? We we all know after going through developing an Erv renderer that everything just boils down to calling a method. But the question is what message is this thing actually call and we don't know what would be nice if we could know that we could translate these directly into method calls and skip this cash key all together.
So unfortunately, we don't know what that will do. And if we did we could actually eliminate a whole bunch of this diagram. We could eliminate we could eliminate this finding a template since we are able to do it at compile time. And actually we could eliminate all of this at run time. We would have to do none of it. Okay. Spoiler spoiler alert, unfortunately, if we did this at boot time, it would mean that we would get a slow reproduction boot time, but we would have overall lower memory because we could have memory usage because the
parent process could compile an advance and then do that before Forks any children. We could also have a faster run time if we were able to do that because we would have no more cash check penalty. I'm going to take a quick detour here. I want to show you something really odd behavior. I ran into while debugging this here. We have three templates on the left we have left to templates are just rendering a collection. This one is rendering The Collection. This one is rendering the cast collection but sing cast and this is the temple that it's actually rendering each of them a rendering a
thousand customers and the question is which one of these is slower the cast of the nun cast template. So people think that the non-cash temple may be slower. But now it's the actually the answer is of course. It is the cast one that is slower. Otherwise, I wouldn't be showing you the slide. You go. Look at a benchmark therapy issue for The Benchmark. I'm not going to put it here cuz it's kind of long. But if we run it the the cast version is actually slow or is 5.6 times slower. I couldn't believe it when I was looking at this I was
convinced that the cash didn't work. I was convinced convinced convinced. It did not work. But there were cash entries for that in the in the cash for that particular template. So then I had to wonder. So I profiled the cast and it turns out that Caskey calculation was actually more expensive than executing the Temple of itself. So I had to say okay, where does this actually pay off and if we look at those that's the old template the new template. I had to make a do that much
work for them to become equal. If you do that much work in your new Temple now is equal so there are there approximately the same. So what that means is that cash does not seem to stop mean fast. All right. So let's talk about speeding up templates are main weapon for making Temple Run during faster. But well as maintaining developer of ergonomics is essentially doing static analysis on our templates mean so hot so far that it's hard to get some of the data out of our Temple statically, but that's one of the optimizations that we actually do it at GitHub. We're starting to extract this
into into a jam and hopefully push it upstream and here is the initial initial work on that done by John Hawthorne. One of the people on my on my team and if you go take a look at this, it is a work in progress, but it is being extracted from real application. It allows you to do they make this call that just freaking piles all of your template and essentially the way that it works is it looks at your yarrabee Templeton it says okay in this first case, we know we can freaking pilot. It has no locals. We know we can freak Apollo second one that has locals but there were able to tell what they
are without running and its third case it cannot precompile the dino. Locals template because we don't know what it is exactly who are able to predict essentially what the what the template Source will be for those first two, but not for the last one. So this is this is two parts of the puzzle. This is pre compiling with templates or one part of the puzzle is apri compiling tablets. The other part is figuring out what method we're going to call. So I want to talk a little bit about rendering methods and a change that I would like to make and rails. It's slightly backwards compatible. That's
essentially the change I would like to make is something I like to call the same format assumption essentially what this is is in this case we have and is this one ambiguous? Yes. We have an ambiguous template rendering issue here where this first one we don't know what it's going to render. We know that second one will render a ping. Oh, I'm sorry. Caption people I'm speaking fast. If I read the captions do I go into an infinite Loop if I read the captions do I go into an infinite Loop?
Alright feeling this. In this case in the second case where no we know we're going to be rain during the Ping. But in the first case, it's kind of ambiguous. We don't know if it's going to be what it's going to be. But what I would like to say is well since we're inside of an HTML template, we should assume that it's going to be a tutu. No sew a child of an HTML template should also be an HTML template unless otherwise specified. So here is another example with with an ambiguous Ranger issue in this case. What we say is well, it is HTML, but we don't know where this is going to
go. We know the second one is supposed to be HTML. Sometimes this first one can raise an exception and sometimes it will it will be a ping where we know the second one will always raise an exception because there's no HTML know HTML case Now what we can do is if we make this if we make this assumption, I think that we can always optimize our templates. So we in this case we can say well we know that it's supposed to be HTML. We know that giving it given the same format of something. We assume that that child template is supposed to be html mean is that if you have an
ambiguous template, it could raise an exception and you would have to change your code to be specific about the render format that you want. You have to say while I really want to pay me here. I know you're inside of an HTML template, but I really want to Ping. This would allow us to optimize every single every single render call and be able to predict the method that we're going to call. My theory is that this same format assumption will work for 99% of the apps today. I guess the most HTML templates have corresponding HTML child templates, which means that we could optimize this case.
So if we're able to do this particular optimization what it would mean is that when we actually compiled the temple will generate those method calls and embed those into the ER be rather than doing the look up and paying that cache key cost. At what cost low hopefully low the cost as you need to put format when you're enduring tanks. It's all right. So we have a we could do another another there's another thing we could do or we have no backwards compatibility problems. And that's essentially what we could say is well
in cases where we know that it's ambiguous. We won't optimize it will just render a template that looks like this will fall back to the original thing. And then in this one where we do know what it is we can we can raise an exception. So okay. I'm going to wrap this up very quickly now. So today are presented a couple of I presented some really bad jokes. Excuse me, some really good jokes, you're an hour of your time. I apologize. I've also presented some of the some of the things that we've been working on. It works its feet up speed up rails, and I want to end
here with a few few lessons that you can take in general for your applications at home. And if you can always try to be context-free don't depend on side effects in your application. It means that when you're looking at a piece of So you're able to reason about it with in isolation? You don't need to know about the rest of the system. You don't need to know who's calling you or in what context you're being called. You can just look at it and reason about the code. Now. This is kind of the same thing, but be consistent always right functions that have the same behavior calling a function
should always do the same thing. Otherwise the system can become too hard to understand also cash does not equal past Benchmark all of your things before you just enable cast so try benchmarking it then cash it then try benchmarking with cash and able and also, please keep building application. Please keep riding Ruby code so that I can continue to write rupee code into the future. Thank you so much. All of you. It was a pleasure to be here.
Buy this talk
Access to all the recordings of the event
Buy this video
With ConferenceCast.tv, you get access to our library of the world's best conference talks.