 I was starting late because of my ghost short, then we'll be on time. I'm really excited to be here. So I took a selfie with the thing, and I'm really mad, like I'm really mad at making slides as you can probably tell they're not very great, especially this, like this, you're never supposed to do like a vertical photo. So I rotated it to horizontal. So it still doesn't look very good. Anyway, as Jeff was saying, my name is Aaron Tatos. I'm also known, I'm also known as Panda Love, and this is what I look like online. It's my online, online photo, that's me. Two cats that I love very much. This one is Gorba Jeff Puff Puff Thunder Horse. He is adorable, and I love him. This is the other one, her name is C-Tac, C-Tac Airport Facebook, YouTube, Instagram, Snapchat. And we just made for that because she does not care about her name at all. So that is her name. And I also noticed that we have some cats out here on the building, which I think is very, very cool. So yay, yay, cats here. And also I have brought stickers of my cats with me. So if you want to come say hello to me and you don't know what to say to me, say, Aaron, may I have a sticker? And I'll just say, yes, here, have a sticker. And then you can either end the transaction here. Or ask me other stuff if you want. I am, in fact, on the Ruby Core team, which is responsible, team responsible for developing Ruby language. I am also on the Rails Core team, which is responsible, the team responsible for developing Rails. And you may even remember me from such talks as Katrina's talk yesterday, where I am, in fact, famous for remembering maximum-signed 32-bit integer. Which is this. I work in a very small company called Git Hub. You may have heard of it. We got acquired recently, and I actually had a change to my desktop background because of that. It is the only legit company I've ever worked for. I love Git, but I will not force push it on you. So people tell me that I really need to branch out on my puns, but honestly, it's just so easy because, like, oh, sorry. It's just so easy because we have, there's another window to do a crash. It's just so easy because we have a pump channel, it works so I can just go in there and cherry-kicks. But I guess what I'm really trying to say is that I'm not a big fan of websites, like buyer stuff, and how to work for us, et cetera. So anyway, yesterday, Git gave a very interesting talk, and he was talking about self-promotion, and I decided that I needed to do more self-promotion. So I had a meeting with my boss, and I told her that I would like to promote myself. And she told me, unfortunately, I just can't give myself a promotion like that, so I thought, all right, well, I guess I'd better do better, I'd better do a different type of self-promotion. So this morning, I took my selfie and tried to airdrop it to beat. It was exactly what I wanted. This is a type of self-promotion you do can do. Anyway, I love going to networking events, especially wireless networking events, but unfortunately, the Wi-Fi doesn't work here so well. I decided to do personal networking and tether with my self-promotion. Sorry, I don't write any of these jokes for you, if you're all for me. Anyway, I love local, I love supporting local businesses and local stuff, so every time I go to a new place, I try to have local things there. So yesterday, I decided to have local beer. I'm gonna taste the Rocky. It was delicious. So thank you, all right, so I'm from Seattle, which is an elevation is 187 feet, so it's very close to, pretty close to sea level. Here, we're here in Denver, Denver's elevation is Denver's famous for being a mile high city and we're around 5,000 feet up here. And it's actually really good for a speaker that are coming from out of town because it means that we're under a lot less pressure. And so do you from out of town, like some of you from Europe and stuff, so feet doesn't make sense, so I translated this into furlong. Anyway, thank you, thank you, for having me, I really appreciate it. You're letting me waste all the feet. So one thing I wanna do, though, is how many of you are here from Turing, how many of you graduated from Turing? Yes, yes, that's amazing, amazing, congratulations. That's really awesome. You passed Turing, yeah, now Turing, sorry, I need to promote, I feel like Jeff isn't doing enough to promote self-promotion here, so I'm doing that thing for him. Okay, all right, all right, let's actually talk about some technical stuff. You paid good money to be here, so I feel like I probably haven't done that. All right, so this talk is titled, the view is clear from here. I'm gonna be talking a bit about Ruby and I'm also gonna be talking a bit about Rails, so we'll talk about Ruby stuff and Rails stuff. I need to warn you, there will be code, there's gonna be code in my presentation, there will be Ruby stuff, we're gonna talk about Ruby, there will be Rails stuff, we'll talk about Rails. And I know some of you here are not necessarily Ruby or Rails engineers, but I also wanna present some just general software engineering practices too, so that if you don't do Ruby or Rails, at least you can implement these practices in your own projects too. So Rails is an MVC framework and for those of you that don't know, MVC stands for model view of controller and the way that these components actually work together inside of a Rails system is first a request comes in, the controller handles the request, the controller asks the model for data, the model returns data back to the controller, the controller passes that data to the view, registers an HTML, passes that back to the controller, and then finally sends it up to whoever made the request. Now, many years ago, I worked for a company that was building a system to do pop-up locking and the system that we developed there was, it was basically a pop-up locker, but we actually called it a a modal view controller. Thank you, Jeremy. It controls modal views. This is different from total MVC, I'm glad I got one person. All right, so in Rails, the different parts of the system are, here we have the controller that's called action controller, the model area that's called active record, the view area that is action view. Today, we're going to talk about that is action view. Today we're going to focus on the, I usually typically work on active record, and if you see many of my presentations, I'll be talking, I talk a lot about active record, but today I want to focus on the view layer, which is this action view area here. That's the place we're going to talk about today. So, as I said, we're going to talk about action view. Action view has a few different responsibilities. Basically, what it does is it finds templates, compiles the templates, and then executes the views, and we're going to learn about all these different processes. And the first part, we're going to talk about finding templates in detail, but essentially, action view will look for files on your file, templates on your file system, and then compile it. In other words, it will traversal your file system. Wow! Yes! It energizes me. So, let's talk about these view templates. In Rails, we use a thing called ERB, and by default, Rails uses ERB. We're going to talk about ERB today, but in general, all the things I'm going to say here applies to all templating languages, not just ERB. So, ERB was originally developed by Evan Stecchi. He also developed the DRB module, which you may have used. This is an example of an ERB template. So, basically, we just have some HTML tags here and then a couple of these special tags, which all they do is they call a function and then return the value and print that out. So, this is what a template looks like. Now, the way that we... If you've done any Rails development, I'm sure you've seen this. The way that we actually compile these templates is we use ERB like this. We just say, hey, read in the file, call ERB.U that actually compiles the template, and if we say, puts template.source, we can see the source code of the template and then we can actually evaluate the template. Now, all compilation does is it takes that template that looks kind of like HTML and converts it into a Ruby program. That's all it does. So, if we look at the source, if we actually print out that source, it'll look something like this. So, this is the compiled source and it's not the prettiest Ruby code that you've ever seen, but it really is just Ruby code. And if we execute this, we're gonna get an error, but the reason we'll get an error and it's pretty clear from this code is we haven't defined a render form function or a link to function. So, when the code executes, it's gonna blow up there on those lines. So, in this example, what I did is I just defined the render form function and the link to function. These are just functions. And then we can actually execute the template and it'll output the template, the results of the template. So, we can see from the output, this is just a return value of it. So, you can compile the template and execute it all outside of Rails. Now, I wanna talk about a little strange and not fun challenge when building a templating system, especially inside of Rails. And we saw that ERB has a couple translations. There's two, there's the one up at the very top that it just executes something and then outputs the data, the return value of that execution. So, whatever Ruby expression you put in there, it runs it and outputs the return value. Then we have another one here, that second one, all it does is it executes a Ruby code. It doesn't output the return value at all. It just executes it. So, what I wanna show here is a challenge for capturing blocks. You may have seen something like the right-hand side over in a Rails application where you can capture what's inside that block and output it later. So, if we execute this code on the left-hand side to run this template, what is the output gonna be? I don't want you to answer it, just think about it. Well, think about what your answer might be. Which one of these will it be? Well, it's actually gonna be a syntax error. I'm gonna show you why. So, this is what the compiled output looks like. We can see here we have that capture do, and then it tries to do a 2s on that, and then later on we have this in that doesn't actually go along with the do. And the reason is because if we look at these ERB, these ERB tags, ERB isn't smart enough to know that that's actually a block. It just does a straight translation. So, it's translating it straight over into the hey, call this function, and then just print out the results. And then the end is being translated into hey, just call this function. That's the idea about Ruby code and stuff. So, that's why we'll get a syntax error here. But how does this actually work in Rails? How does this actually work in Rails? What Rails has to do is Rails has to detect that inside of that ERB tag that you're actually calling a block. And I'm gonna show you how it does this. I don't want you to read this. You don't need to understand it. I'm just showing you that what it does is basically parse the Ruby code in there, create it, but then call it a block. So, it's possible to trick it and possible for it to get it wrong. Don't read this, don't understand it. It just doesn't. That's what it does. So, we've gone down... We've gone down a rabbit hole a little bit. I want to step back a little bit. We're getting a little too into the weeds there. I want to step back and talk about different ERB flavors. There's a few different flavors of ERB. There's the ERB that's the original one that ships with Ruby. That's the one that we've been talking about. There's another one called Erubis, or Ian Ruby's, I'm not sure how to pronounce it. That's the version that Rails uses for a long time. At first Rails used the ERB version, then we switched it to Erubis because it was faster than ERB. And then now a new one is out called Erubi, which is faster than Ian Rubis, and Rails now uses that third one. It's faster than the previous two, but they're all compatible, so you don't notice a difference. You just write your ERB and it works the same, basically. So, let's talk a little bit about ERB performance. I don't want this to be a Rails-specific or actually temple language-specific. It's not specific to any language or template, but we're going to talk about speeding up ERB, but you can apply these techniques to the building language that you have. So here we've got an example where I'm just going to render a template like we did in the previous slides. It just executes the template and then times it. It sees how many times we can render this template per second. If we execute it, we can render this template about 27,000 times per second. So we can do better than that, and the way we do better than that is we actually cache this. We say, hey, well, every time you call ERB.new on that same template, it's going to have the same results. We don't actually need to do that thing over and over again. We can just do it once and then evaluate the template. So in this case, we compile it once and then evaluate the template each time we execute. If we compare that, we'll see in this case the original case is still rendering about 27,000 times per second. Here we're able to get a 2x performance boost and render it about 63,000 times per second. So we skip that compilation step. We can get a good performance boost out of this. Now, we can go even further. Every time we actually evaluate that template, we're calling the eval function, and calling eval isn't actually a very cheap operation to do. So what we can do is we can actually cache that eval statement. The way that we're going to do that is we'll zoom in on this later. Don't worry. I'm going to read it too closely. So what we do is we take that Ruby code and we define that Ruby code from the ERB template and define a method that contains that Ruby code and then execute it. And if we do that, we're essentially caching the eval. We define a method rather than eval each time. And if we compare all those together, we're still doing about 27k for the original per second and 65k for the cached compilation but for the method call version, we're doing about 1.4 million times per second which is 52 times faster than our original one. So this is the technique that Rails actually uses for rendering your ERB templates. It generates methods from those ERB templates and we're going to take a closer look at that because I think it's kind of important. Basically, this is what it basically does. We have a template at the top. We compile it and then we turn it into a method and we only do that once. Then every time we render your template, we just call a method each time. So here we have the template source. The template source gets compiled here. The compiled source is turned into a method here and then we just call that method. This is what the, as we were to print out the method source, it would look like this. It just looks like a normal method and inside that method body is the stuff we saw from the ERB compilation. So later on, we can just call that method each time rather than define the method. So simply put, templates are translated into methods in Rails. Now since we know these templates are translated into methods, we can do a couple things with that, interesting things with that information. One, if we execute this, let's say we put this template in Rails on the left-hand side here, just put that in Rails and you print out all the methods that are defined. You'll see in the console output a bunch of these strange-looking ones that are like app view users, blah, blah, blah, blah, blah, but you can actually see these generated methods. So you can see that they're generated. The other thing that we can do is we can measure their size. So we can say like, okay, how much memory does this particular template take? Now when it's executing this, when it's sitting there doing nothing, how much does it take? And we can do that by just saying, hey, give me the method and we can ask the Ruby VM for the instruction sequences for that method and then measure the size of those. And in this particular case, it's about 1200 bytes. And if we increase the size of the number of bytes, we get larger, but we can actually measure the amount of memory that our templates are taking. So let's talk a little bit more about template handling in Rails. Everything we've talked to, everything we've spoken about up until this point are just techniques that we can do in Ruby. They're not Rails-specific. They're techniques that Rails uses, but you can use them in your own framework if you would like. So now that we know how these methods are, how these templates are compiled, it gives us some insight into how certain behaviors about the templates. So from here on, we're going to talk about behaviors of these templates inside of Rails, specific to Rails. One thing is instance variable visibility. So say you have two different templates and you access an instance variable, we know that between those two templates they can both access that same instance variable. And the reason they can do that is because we just defined two methods on the same class. They're just regular methods. We know that regular methods on the same class can access some instance variable. And since it's the same instance, we know, oh, this is the same instance, so we can access an instance variable like it's a regular class because it is a regular class. Now, that being said, instance variables in your templates, you can quote me on this, don't use instance variables in your templates. And the reason I say that is because if you look at these two templates, you have to ask yourself, who defined that instance variable? Where did it come from? Do I need to execute a different template before this template in order to get the instance variable that I need? So don't do this, use local variables. In fact, at work, so we're going to talk about local variables now, but at work in our application, we don't allow the use of instance variables in templates specifically because of the reasons I told you before. They're essentially globals in that you don't know where they're defined, you don't know where they're mutated, you don't know what order things are being executed in. So it's best to avoid them, and that's one thing that we do at work is we don't allow that, and we use linting to prevent people from using local variables in the templates. So let's, or excuse me, instance variables in the templates. So let's talk about local variables. Rendering locals looks something like this. In this case, we are rendering a template called content, and we're passing it to locals with a name, with a name, and that's board being my cat. But we have kind of a problem here. Like, let's say, let's look at that content template. So this is what the content template looks like. It says hello, name, right? Now, we have a problem here in that let's, actually, let's take this template and, given the techniques that we used earlier, we know that it's compiled to a method. Let's look at the method that it's turned into. So this is the method that it's turned into. But there's an issue here, this name here. That name is actually a method call. We don't see any local variable named name. So if we executed this, we're going to get an error. Ruby is going to try to call the method name and that doesn't exist. What we wanted was a local variable. So we need a scheme for defining local variables inside of these generated methods. So the way Rails does this is it defines a preamble that declares all of these locals. So, in our previous example, we had this content where we say hello, name and Rails will say, alright, we're going to define a preamble, excuse me, we're going to define a local's preamble here. We have a preamble that basically says we're going to declare a local variable named name and it gets it out of this hash here. So the hash is passed in from the outside template. But what this means, this particular technique causes a couple problems for us and one of the problems is that the templates require context. If we look at this template in isolation without knowing who's calling it, we can't tell, you and I can't tell, or is that a method call? We don't know. And neither does Ruby. And the only way that we can know this is by knowing about the calling context. Is this a method call or a variable? It's hard to tell. So, if we have, if we look at the calling templates, transition, there we go. So we're seeing in this particular case we can actually mix and match this. In the first case here we have a local variable named Warby. But in this case it's actually a method call. We don't have a local. It's going to call a method. So the issue with this is we can't compile templates in advance. Because we don't know the context within which they are being compiled. So we don't know is this a local variable that needs a preamble or is this just a regular method call that doesn't need anything. So we have to actually wait until somebody says hey, render this template before we can go compile it. So this is bad for servers like Unicorn because it means that we can't compile all the templates in advance. Each child process has their own version of the template and it will use up more memory. So it's not very good. The other problem with it is it's not very good for memory usage. The other problem is that we can end up compiling the template too many times. So, for example, let's say we have this situation where we say render content and in these two cases we're passing a friend local. Maybe the template doesn't use it. Maybe it's never using that local variable. But if we look at the compile content, the compile methods, we'll see here we have two different locals, two different preambles. We have one for the name in this case and in the second case we have one for name and friend. But we have to generate two different methods because we have two different locals or two different local preambles. So this is not good for memory usage because now we have obviously we have two different cases where we could only just have one. So you may be asking yourself Aaron, this is nice. This is fun. Interesting information. I'm engaged and enjoying your talk. But what am I going to do in my application today? So we talked about this problem of lack of precompilation in multiple comp... Compiling templates multiple times wastefully. Now there's nothing you can do you as developers can do about the precompilation but that's something that the Rails team, we, me and the other folks on the Rails team are working on a solution for. But as far as the compiling templates multiple times wastefully, there is something that you can do and that is to make sure that when you render a template the labels have the same signature essentially. Make sure they all have the same hash. That way they only get compiled once. So always pass the same locals to individual templates. So let's take a look at the render function next. It's a very high very high level. The render function basically finds a template, compiles a template, calculates a method name and calls the method and we saw this entire process. If we look at it from a logic graph here, whatever these are called we find a template from the cache and we ask hey, have you been compiled? If not then we'll compile you. If you have been compiled then we'll just call the method. That's it. So finding a template, this is the other piece of the puzzle we've learned about how templates are compiled and run. The last bit is just how do we actually find these templates. And finding them, to demonstrate finding issues of finding them, I built a little test application and templates that are rendered depend on the requested format. Oops. Templates rendered depend on the requested format. Rails tries to figure out what template is rendered based on the content type of the descent. So for example we have a controller here, the user's controller and it renders the index template. So by convention we look under the user's view because this is the user's controller and the action is index so actually we're saying please render the index so we'll look for the index template. But in this case in our application we have two, we have the index HTML and index.erb and index.xml.erb. So here's the content of those two templates. One says xml template the other one says users. I probably shouldn't have made that HTML. Sorry. Please remember that is HTML. So if we change the accept header as we say we want HTML or we want xml we'll get different views rendered depending on that accept header. So here's essentially a table of what we say. Say we'll do a curl for xml. The response is xml. We render the xml template. If we curl without any headers we'll get HTML. If we curl with HTML we'll get HTML. So this is what essentially what our matrix looks like. So in order to know whether or not a template has been cached we have to maintain these cache keys. Part of the cache key is the format. Actually I have a list of all of them. The cache key is the local variables because that impacts the generated code. We have a format, the locale because you can have like a .jp or .en or es on the template name. And also the format and variant like if you have an iPhone I can also impact the file name so we have to know all those things. But unfortunately we can't know those things in advance. We have to wait until it's actually being rendered to look those things up and then say oh yes this is compiled enough. So this is another hurdle for us compiling templates in advance. And we also have some strange render migater that I want to demonstrate here. Let's say we have the same controller. But now we have some partials in here. We don't have an xml index anymore. Just an xml HTML. But we have two sub templates here like a ping.erb and xml.erb. And if we look at the index HTML that sort of looks like it just says render my template and inside the ping one it says I guess this is the ping and inside the xml one it says xml is cool. So when we render this template which one of these do you think will get rendered? When we make a request which one of these my templates is going to get rendered? Don't answer. Just think just think we're going to get rendered. So if we say give me xml we're going to get an error saying hey there's no index xml. If we just do a normal curl it's going to render the ping. So it renders index HTML.erb and it says it renders the ping.erb. If we request HTML we actually get an error saying hey there's no HTML templates. I tried rendering HTML. If we use a browser we also get an error trying to render. This is what the browser looks like. I tried to render my template but there's no HTML version of the my temple. So the bad thing about this is if you look at this template we cannot predict what this render will do. Is this going to render a ping? Is this going to raise an error? We don't know. So this is very strange behavior in my opinion. The other thing is here we go. Let's say we have this control this is our bare renderer controller in index. Now let's say we do format.html. Maybe I'm sure you've seen this before. If you do any Rails development you're like I have different formats I'll just do an HTML one. If we do this, if we do this new version and we run that entire test matrix again then actually the responses are more consistent. We get an error for the XML one and then every other request gets an HTML error because we're trying to render HTML. Now if you think about this behavior I think it's kind of crazy. This behavior of this call to render here this call to render depends on what context this render is in and if you're looking at this template how do you know? How do you know what context you're being called? It means we cannot look at this template and understand what it will do next. So in other words templates are not context free. And I've been going on and on about prediction and consistency with template behavior and now I want to talk about why. So in this case we have, this is our graph of the logic that's going on after doing performance testing on our systems at work we found that unfortunately compiling it, asking whether or not a template is compiled, that's cheap. Calling the method is cheap but actually finding the template inside the cache is very expensive because we have to have all these keys. So it would be nice if we could get rid of that if we could get rid of that step there. So in order to get rid of that step what would be neat is if instead of looking up in that template cache if we could just render or if we could just put those method calls in there directly. So for example in this case we know based on all the previous knowledge in this presentation that this render call is eventually going to boil down to just a method call. It's going to boil down to a unique method call and if we knew what that unique method call was in advance we could just put it right there. If we knew what that method call was we could translate it into something like this where we just call some randomly generated method but we know what it is and we don't have to look in the cache anymore. If we knew that we could say, oh you know what I don't even need this step anymore because we already know. And in fact we wouldn't need any of these steps because we already know that is a very slow transition. Oh my god. This is the first time I've given this talk and you can't tell. Oh my god. Let's wait for this transition to crumble. I'm a training professional right here. So anyway, it means that we wouldn't need any of those steps anymore. Unfortunately it would slow down production time because we would compile things in advance but that could be a limited by bootstrap. We could cache that. It would lower our memory because we could compile everything in the parent process and we would actually have a faster run time because we no longer need to check this cache anymore. So I want to take kind of a detail where I know we started late but I'm going to do it anyway. Ha ha ha sorry Jeff. Alright so I was researching Oh it's started on a deep tour. Yes I'm taking a deep tour for the deep tour. So I want to what this prediction technique that I'm talking about we actually use it at work. So it's one of the things we use on our application at work and it's one of the things that I'm working to upstream. So part of the responsibilities my team does is take stuff that we have in GitHub that's not really core to our our business in upstream and make it open source. And we want to upstream this and we want to make it open source so I've been researching how to do that which is why I'm talking a lot about ActionView today. But in doing this research I ran into a very strange issue so I actually filed a ticket for it which you can look up later and you'll see why. So we have three templates here. We have these two templates on the left they both render the template on the right. They're both collection rendering. Now we have a list of customers that is a list of active record objects that are customer objects and there are a thousand of them. Okay. Now if you look at these two you may think to yourself okay which one of these is going to be faster? We have the one on the very left that doesn't know catching and then we have the one in the middle that says cached troops so we're going to do some caching. Now which one of these two templates is going to be faster? Obviously the one on the left is going to be faster because if it was the one in the middle I wouldn't be talking about this. So this one is the slow version. The cached one is the slow one. And you can go look at the benchmark here I'm not going to put it in the slides it's kind of long just the issue. You can go check it out but I will show the benchmark here. Actually the one with cached is 5.6 times slower than the one without cached. When I was running this benchmark I was convinced I was convinced the cached didn't work. I was convinced I was convinced it did not work. How can it work? It's 5 times slower. What is this? So I started debugging it and I found that there were entries in the cached. It was querying the cached and I was hitting the cached. So I said okay well I guess I have to profile this now so I profiled the cached and it turns out like you don't need to read these I'm just showing you that I actually did some work. So I profiled it and I found that what this actually is the very top, that top frame there what it's doing is it's actually calculating a cached key. It's calculating the key for the cached. It turns out that cached key calculation was more expensive than just rendering the template. So then I had to figure out okay where is the payoff? I know we're getting cached hits but there has to be some sort of payoff. So I figured that out the old template is on the left the new template is on the right and I had to do this much work in order for the caching to pay off. So this is our template that runs a thousand times or whatever if we benchmark this then the two are about the same we have a non-cached version. So they're same-ish there which means that you need to increase like if you're going to cache a template you need to have a very complex template that does a bunch of stuff. So in other words, what you can learn from this cached does not mean fast and with that I want to talk about making render fast so I think we have a couple of choices for making render fast we can always make this render call I think we can either always make the render call fast or we can make it usually fast and I'm going to talk about making it usually fast because I think that this making it usually fast is one of the smallest impact on existing applications today. So the technique I want to use for making it usually fast is something I'm calling the same format assumption and what that essentially is is if we're inside an HTML template so this is index.html.erb and we specify a format so we know that one in invents so we can calculate that method in invents but what I want to say is if we're inside an HTML template we're going to assume that if an HTML template exists that matches that name that's the one that we're going to render that's going to be our hit I think this is actually a safe assumption to make actually I'm pretty sure that 99% of HTML templates that render other templates have corresponding HTML templates as well and if you don't have one you probably specify the format now in the case of the ambiguous render ambiguous render problem in this case we have a render my template it's inside of an HTML template and if we look at the file system we see oh we have like pings sometimes we get a ping sometimes we get an exception as we saw from our test earlier so in this case we don't know what the behavior of this one is in this case so we know that this one may actually render or may be a ping this one of course will always raise an exception because there's no my template of an HTML format so the question is do we treat these two the same can we do that and I think the answer is no we can't do that because of backwards compatibility if we did that then your entire application would explode and people would be mad at me so I don't want to do that if we did that if we could do that then we would have what I would call an always optimized situation we know what the renderer is going to do and we can always optimize but I don't want to break people's applications so I don't think I would do that it would allow us to optimize it would allow us to optimize every case but it would also break existing apps and I don't think that's good so my theory for this the only format assumption is that in 99% of cases 99% of templates we do not have an ambiguous renderer issue it's just not a thing it's not ambiguous most of the time we'll have HTML templates most of the time we'll be able to predict them and this is also the same we found this to be true in our application award so I think the same format if we use the same format assumption we can take this index HTML or B and then translate it into direct method calls like this so in this case where we have an ambiguous renderer issue when we know to optimize it we say well you know what I don't actually know what this is going to translate to so the optimized template will just look like this we'll stick with the regular render it'll go through the slow process or the slow rendering process and then just maintain the existing behavior so to wrap this up I presented here some things we do in GitHub but we haven't put them up-screen yet because of corner cases I'm working to eliminate these corner cases which is part of this presentation here today and I want to end with a few lessons that we can learn just in general from this talk first off is when you're writing code, be context free don't depend on side effects it's important that you're able to look at your code and reason about it in isolation you don't need to think about the rest of the system the systems that you're working on are going to be so complex that you can't keep the entire thing in your mind and the only thing, the best thing that you can do is focus on this one particular case and if you have to take into account context you'll have too much mental overhead to understand what's going on the other thing is to be consistent calling a function should always have the same behavior that is essentially the same thing I was saying on the last slide but those render calls that behave differently depending on some other render call over here I don't think that's a good behavior we don't want that, we want to be able to look at our code and say hey I called this function I know it's going to do this and it'll always do that another thing, lesson learned hash does not mean fast it does not hopefully it's faster but that's not necessarily true and the only way we know is to benchmark first so always be benchmarking your applications looking for the actual bottlenecks if I had benchmarked my toy application I would know this is actually not a bottleneck I don't really care to cache it I mean you're not actually going to cache that template introduction but you need to be benchmarking in order to understand where it would be finally this is, I know this is a real specific make your locals match do it, it'll lower your memory overhead have your Friday everybody thank you so much for having me here first question was about what you're saying with instance variables in templates linting to ensure that they're not used in the examples you were looking at partial templates is that true also of the top level templates top level templates that's a very big question because it's tough to pass you design all these instance variables in your controller and then typically the top level the top level template will access those instance variables at work we don't allow that now you do understand the pain yeah how else what is your preferred way to get that data into the top level template so the way we do it at work is we pass in essentially one local and that local is a view a view object we construct a we just construct an object we construct an object that contains all the instance variables or all the context that we have to know about that template and we call that this on there which is nice for us from a testing perspective as well because we can just test the behavior of that object along so this is like an area of my interest I would say in a view template and so forth in my eyes there's always a challenge with view templates that you're essentially changing the paradigm of your programming where we go from very object oriented work on the back end and as soon as you get to the template it's what I would call a functional functional approach our templates today continue to look almost like PHP templates and that we're kind of merging them is that fair is that fair characterization first and then second with now 14 years of Rails or so, 13 years is that the right way to do it actually it's a very good question I think you're absolutely right in your description of the templates and we are it's kind of weird because if you look at if you look at how we actually compile those templates like we went through the presentation today you'll see that they're all just methods on an object so we're technically doing oh it's just you can't see you can't see in my opinion I don't think we're doing it right we know so another motivation for this presentation is that somebody here in Denver who actually gave a presentation at the Boulder RV I think he gave a presentation about a different way of doing views more sort of react style I guess I don't know any react so he's just taking his words for it react style views and he wanted to implement that in Rails too and I've been working with him on doing that essentially the change would be like you'd say render and then you'd give a class name and then some data that you want to pass to that class and it would automatically instantiate that class if you go look at the class it will have a PRB template inside of it that'll get render and you can actually test those in the isolation and do whatever you want to with them whether or not that would get accepted in Rails I don't know I mean I the technique that we're working on together I think it's way better I think it's much better it enforces the isolation the data isolation you literally can't see the other instance variables so it's not limited so I think that's a better style but I don't know if it'll ever be in core it's interesting the problem that's being approached here is like create very complex long strings so do you want to write a complex long thing and then turn it into some complex code and output a complex string or write a complex code like you could do all kinds of insane string interpolations and say like oh we have object-oriented view render right now but drive yourself insane with string interpolation so yeah it's kind of I think sometimes people can look at problems like this and be like this sucks we should do different but coming back to one of the points that kept coming up here seriously you can trade off but this is going to be a ugly problem no matter what you do it's absolutely another problem no matter how you tackle it it's not going to be fun last question for me is historically the view layer in Rails specifically my impression has always been that it is going to be this beginning that no one wants to touch which is also historically the places where you end up individually right the code that everyone else is like yeah it's hopeless just is this now going to be your passion area like you will feel the scene is this going to be the next five years of your life with a smiling action view so yeah your characterization is like 100% on yes it is it is terrible spaghetti code that nobody wants to touch and I like looking at the get history on it I'm like this is old but it's been almost no cheap drink like a few template today you could take back to Rails 1.0 yeah there's been hardly any changes and I think that's actually for the worse I think that in my opinion the code is so complicated that nobody understands it and wants to touch it so yeah I think that will be that is my next area my next area focus right now but I don't think it's going to be as long and arduous journey is working on active record I think once we get this like once we get it to the point where we can take the the stuff that the optimizations that we're doing in GitHub and upstream those into into Rails I think will actually be a really good position hey Aaron I'm DJ thanks for your talk I don't know how to ask this without sounding kind of like a poos kind of like a dirt but it's extra my life as a DJ right now do it so it's 2019 why are we still talking about Rails views I feel like everybody writes job script for the front end now I mean we don't that's true I think a lot of people a lot of people are just writing JS on the front end but there's still a lot of people using Rails views and we use them a lot of work so that's why I'm looking at it do you have any advice for someone who wants to be involved in the Ruby or Rails projects as a new commuter to open source where do they get started Aaron if you know my chance don't so it depends it depends on what you want to do a lot of people say I recommend starting at the edges don't go directly for Rails a lot of people get started a lot of people excuse me you should get started with documentation but I personally hate doing documentation as if you tell for my amazing documentation I prefer doing programming and if you prefer doing programming too it's very difficult to get actually started on Rails and I'll tell you why the reason is because as soon as we get an issue file if the issue is easy somebody hops on and fixes it already because it's such a popular project you'll have a better chance as if you go for dependency and things that Rails depends on so go look at all the things that Rails depends on go look at those gems those things the issues on those there will be more likely to have easy things that you can get started with so I would recommend starting there and once you start there you'll get more familiarity with the you'll start working your way up to getting more familiarity with Rails for itself in that case you'll be able to solve more complex problems in Rails and then be able to contribute in that case too so start on the edges and work your way in it's my advice there's this great project called No Coquetry what's the quote about XML and violence is that your quote? no okay it's one of my favorite quotes that's an old like bash not a word thing hey Erin I'm curious what ramifications for Hamel or Slim or something like that it would have because the lookup obviously has nothing to do with which of those libraries you're using but it seems like there'd be changes in those libraries upstream too no I think those libraries wouldn't have to make any changes at all we could continue so all the changes required in order to do this what I'm talking about are basically static analysis on the ERV that's all going to be inside of the ERV ERV compiler itself so it shouldn't impact any other templating systems it'll probably just mean that ERV is way faster than the other and ERV inside of Rails will be way faster than other engines inside of Rails but that said those other templating engines could apply absolutely by the same technique so I think there's like a reasonable case coming back to DJ's question so template rendering is probably no matter where you do it and like someone has to construct templates it might be the case that you're even if you're not using ERV as like your primary tool you might be using it in a service like fetching those template fragments over the API or whatever there's like a lot of the essential problem that ERV is attacking remains no matter where we're doing our computation somebody's got to do it somebody's got to concatenate the string string cell strings back thank you Erin thank you so much