 I said it once already, in case I'm going to be handing out salami, actually, let's start doing that now. Take one, pass it down. These are the ingredients. Like I said, if you're allergic to anything, like of these, then you probably don't want to eat it. So, okay. All right. I have 235 slides in 45 minutes, so let's go. All right. I'm not going to introduce myself. No time. I'm not going to tell you where I work, no time. I'm insanely nervous, but I can't tell you about that. I don't have any time. But there's always time for cats. I have a cat. His name is Gorbachev Puff Puff Thunder Horse, and I like him very much. But I didn't realize, like, when I got a cat, like, I thought he would be my best friend and we'd go like bicycling stuff together and like go to the park and swimming and all that. Instead, he just sleeps all the time. So whenever I take photos of him, he's always just yawning. Like that's basically it all the time. It's kind of disappointing, but I love him anyway. And you can follow him on Twitter. His Twitter address is Gorbipuff. So I was going to, I titled this talk like real-time salami, but honestly, like I don't get to see all of you, but maybe once a year. So instead, this is like my summer vacation. I want to tell you guys all about the stuff that I did for the previous year. We are going to talk about salami though, so don't worry. Just there will be other things besides salami. We're actually going to talk about food stuff, work stuff, and hacker stuff. I'm stoked about the hacker stuff. I love RubyConf because I think this is a hacker conference. So I'm really excited to talk about that. First off is the food stuff. Like yesterday Koichi-san gave a presentation and he was a professor. Well, me, I'm a butcher. So we're going to talk about meat-curing. And the first thing I learned about meat-curing was that botulism does not mean anti-robots, which I thought was the cause of the great robot uprising of 1863. And it is not Wikipedia must have its facts wrong. So someone should get on that. But actually the first thing I learned is that when you're making salami, you want to use metric. Please use metric. And the reason you want to do this is because you're never working with recipes with a particular amount. You're always working in percentages. You need to say, oh, I have so many kilos of meat and I need to calculate the amount of salt that goes into this particular mix and it's going to be 3% and calculating that crap with pounds sucks. So seriously use metric when you're doing this. We're going to cover hardware first. I use a wine fridge is what it looks like. It's my wine fridge. I cure all my meats in the wine fridge. And the reason I do that is we need to keep control of the temperature. The temperature needs to stay between 60 and 70 degrees F. I know I said use metric, but I'm not smart enough to switch to Celsius. But I use this for controlling the temperature and this is actually for controlling temperature on kegs like brewing stuff. So people use this a lot for making loggers if I remember correctly, but it also works really well for curing salamis. I use an ionizing humidifier. You need to control the amount of humidity that's in the box. And you want to use an ionizing humidifier because it doesn't emit any heat. So it creates humidity but it's not hot. We don't want our box to get hot. And then I'm lazy so I use a humidity controller. I need to set a particular humidity and this thing keeps the humidity in the box at that particular level. And the last important thing is fans. You need to keep a good airflow inside the box. If you don't have good airflow then your salami will mold and that's kind of gross. So the other hardware you need is grinder. A grinder I use a KitchenAid attachment. This is totally great. You can use it. And it's pretty cheap. The most expensive thing I have is this stuffer and it's totally worth your time. You don't have to get one of these. Good quality one costs about $250. You don't have to get one but it saves you so much time and pain that it's completely worth it. As far as the ingredients are concerned, it's about 80% meat. So there's about an 80% pork shoulder mixture, 20% fat mixture. And then we calculate the other ingredients based on the meat and fat totals. So we weigh those together and then figure out how much of the other ingredients we need to add to the meat based on that weight. So you use about 0.5% sugar so you take the weight, multiply by 0.5% and you figure out how much dextrose you need to add to the meat. And this is for the bacteria to eat. You introduce bacteria into the meat. The bacteria eats the sugar and produces acid. We also add salt and the reason we add salt is to prevent bad bacteria from growing. You need to add enough salt that bad bacteria, it inhibits the growth of bad bacteria but does not inhibit the growth of the bacteria that you inoculate the meat with. You use pink salt, cure number two, which is a mixture of nitrates and nitrites. And it's colored pink because eating this stuff can kill you. So you don't want to get it mixed up with regular table salt. The thing is it's about 95% salt and about 5% nitrates and nitrites. So the amount that you have to eat to kill you is actually a lot. You'd probably be like, this is way too salty, I can't eat this much. But still it's colored pink because you probably don't want to eat that stuff. The other important thing is that this contains nitrates and nitrites. The nitrates release nitrites over time and nitrites prevent the growth of botulism. So the reason we want to add this to the meat is because we don't want to have botulism in our meat. Also the nitrites change the meat colors and it's pretty obvious to see the top there is zero hours of curing and the bottom is 24 hours and you can see it's definitely changed color between the two. And then we have to calculate how much bacteria we put into the meat and that's .012% bacteria, which is a tiny, tiny amount. I think maybe like this, I cured five kilos and I think that was something like a gram or two grams or something like that. I had to buy this scale that only goes up to 100 grams. I totally felt like I was a drug dealer or something buying a scale online. Now this particular bacteria takes about 30 days to cure your meat. You can buy another bacteria that takes less time. Supposedly they produce different flavors. I'm not sure. I've never tried the short curing one. I only do long cures and that's mostly because I got shipped like, I think I got a packet of bacteria that's like maybe, I don't know, 50 grams, which should be enough to last me for the rest of my life, I think. So the next thing that you need to add are spices. Most cured meats are pretty much the same except for the spices. So the meat and fat content is pretty much the same. All this other stuff that we looked at is the same. The only thing that really changes is possibly you increase fat, increase or decrease fat, but mostly it's spices. So the next thing I want to look at is the curing environment. You need to keep wind speed high for the first three days. The first three days we keep the temperature high, so we keep the temperature around 70 degrees and our wine fridge stays between 55 and 65 degrees and that kind of sucks because if you notice from my last graph we need to be at 70 degrees, which is why I have to use that beer thing. So you can either use the beer temperature controller or you can do what I did and hack your fridge. This is a little microcontroller that I have hooked up to the fridge to control it to be 70 degrees. We also keep the humidity at 90% for the first three days and then we drop it down to 65% for the rest of the cure. You need to keep the wind speed high during that 90% humidity because that's really the time when bacteria are going to grow. So if you see my setup here you can see like, oh and the arrows are misaligned, that sucks. I had to resize for this projector and now the arrows are totally wrong. Anyway, right there in the middle we have is the temperature controller and behind it you'll see the humidifier and you can see like, this is a picture from behind the box. The humidifier has a tube that runs into the box and that's actually what pipes the humidity into my box. So the humidifier doesn't take up any room in the box. And I want to tell you a little bit about addiction. This is a face of an addicted cat. These boxes aren't built to have 90% humidity inside, right? So all fridges have a little drip tray in the back where when condensation, when water condenses the water drips out the back and out into your apartment or whatever in a little tray and then that evaporates. But they're not built to handle 90% humidity. So my little drip tray was filling up. So what I did is I ran a little pipe down to a larger container and that would start to fill up with water and I noticed that my cat was starting to drink the water. And my fiance says to me, you know, you can't, he loves drinking that water. It must taste like salami and I'm like, no, it can't possibly taste like salami. It's condensing on the cooling plate in the back. How is it possible it will taste like salami? And she kept saying, yeah, it tastes like salami, it'll taste like salami. And I'm like, no, no, no. So finally I grab a spoon and I'm like, fine, I'll try it. Try it, it totally tastes like salami. So I had to put a cover on it and actually like tape the cover down so that he wouldn't like lift it off and drink the salami water. So anyway, I want to talk a little bit about safety and why this meat won't kill you. This meat, if any of you have been in the food service industry like me, you'll know about the danger zone. This meat stays in the danger zone for a very long time. So why doesn't it kill us? The reason it doesn't kill us is first off, we add salt and this salt prevents bad bacterial growth. So the next thing that we add is we add nitrite and this kills off botulism but you have to be careful with the nitrite because 22 milligrams per kilogram is a lethal dose. So if you weigh yourself and you multiply out 22 milligrams per kilo of your body weight, you can kill yourself with nitrite. So you have to be careful. But we use pink salt for safety. It's pink, pink means safety, right? So the next thing that keeps us safe is acid and this is produced by the bacteria that we introduce into the meat. The meat eats the sugar or the bacteria eats the sugar. The bacteria produces acid. The acid prevents other bacteria from growing. And you can actually see this happening by measuring the pH of the meat as you go over time. So what I do to check for safety of my meat is I measure the pH. I bought it this fancy pants pH meter and I read the pH on it. The other thing is water loss. After about 30 days, I measured about a 45% water loss which kind of sucks because it still has the same amount of calories. It's just more compact. It's not nice for somebody who's trying to watch their figure like me, especially when it's sitting next to your desk. Anyway, so 30% minimum water loss is what you need to look for. So if you're curing meat, you can tell when it's done when you hit 30%. I usually go down to 45. But since there's no water, no bacteria or molds can grow after the water has exited the meat. So we have short term safety, which is our salt and nitrite medium term safety, which is the acidity of our meat. And the long term safety, which is the amount of water in the meat. And the final thing is that we can introduce mold. So if we're having a mold problem, we can introduce our own molds to the outside of the salami. If you've been to a fancy meat place, you might have seen salami that's covered with white stuff that is mold. Don't be afraid of it, it actually makes the salami taste better. So now we're gonna move on to work stuff. Sorry, so I wanna talk about streaming and fermented sausages. So we're gonna talk a little bit more about salami. This is a salami party, isn't it? We'll look at how to get the salami date online. But I also wanna show how streaming works in Rails 4. But first I wanna talk about template rendering today in Rails 4. Specifically, we're gonna talk about template rendering, but we're gonna talk about it from a fairly high level. I don't wanna dive into the internals today, and it probably wouldn't fit on my slides. So we're gonna talk about how template rendering works, and then we're gonna contrast that against streaming. Today, template results are buffered. So when you write out all of your ERB or your Hamler or whatever, all of those results are buffered and then sent down to the client. Now the thing that sucks about that is that clients are blocked while they're waiting for Rails to work. So while you're figuring out all that template stuff, calculating it, putting it into memory, the client sitting there going, okay, cool, I'm waiting around, waiting around. And then finally, it gets some data that can actually do some work. It would be nice if we could send down some data so the browser could actually get to work while we're doing some calculations at the same time. The other thing that sucks about this type of template rendering is that the entire page must fit in memory. Which means that if you have a very large page, you could have a huge amount of memory growth with your particular process, and that kind of sucks too. The other thing is that we can do IO and CPU calculations in parallel, even in MRI. So we're not gonna get totally into parallelization in MRI today, but you can actually do IO and CPU calculations at the same time. So if we can get that sort of parallelization out of our Ruby process and out of our clients, what is the point of buffering? Why are we buffering all this data? So with that in mind, this is why I created Action Controller Live. Action Controller Live is a module that you can mix into your controllers and get an IO type object on your response. So the way you use it is like this. You mix it in, and then you can do stream.write, and you can actually write out data, and it gets sent down to the client. It gets sent down to the client in real time. I wanted it to act, I wanted response.stream to act like an IO object. And the reason I wanted it to do that is because I buy into the Unix philosophy, which is everything is a file. So I want to treat everything as a file, including my response, which is why I was really set on having an IO object in my response. So I want to look at how we actually implement this inside of Rails. Like how do we actually do this? Let's dive into the internals of how Action Controller Live works. We're gonna look under the hood and see how it works. This is the API that we want to have. Like this is what we want it to look like. We want to set a response, status, set some headers, write to our stream, and close the stream off. So we need to accomplish this, but what we have is this. This is the rack API. We have to return all of that stuff at the same time. Even though we want to be able to do that piecemeal, but rack wants us to return it in one step. Ideally, we could calculate this stuff lazily and write it out to the client as soon as we calculate it. So the way that we start is we need to wrap this with a response object. Wrap with a response object that looks something like this. And I've actually simulated Rails down here at the bottom. Like this is basically what happens inside of Rails. We set the response on the controller. We call your action on the controller. And then we have to return all of this data back up the rack stack. But the problem here is that we're still buffering. We haven't actually solved our problem. You can write to the stream, but the stream is still buffered. So how do we solve this? We need to be able to do calculations in the controller and return back up the stack at the same time. We do that with a thread. So we can say, okay, let's call the controller index in a thread. Cool. So now we're calculating the controller index in one thread but returning up the stack in the other. The problem with this is that, well, maybe you didn't finish writing out the headers. And it's already returned up the stack and started writing data out to the client. We're screwed. What do we do? We have to block. We need to block right here, right there, stream.await. We need to block there until somebody's actually written data out. So you have to calculate all of your headers, set all the headers, and then as soon as you actually want to write the body of the response, then we'll say, okay, time to return back up the stack and start emitting data to our response. The way we do this, the way that we accomplish this is we use a latch inside of the buffer. We say, okay, the main thread calls a wait, and a wait puts the main thread to sleep. And the main thread just sits there until somebody calls release on the latch. Now when you say response.stream.write, that says, okay, we're now going to release the latch. And once we've released the latch, then the main thread comes back awake and says, okay, let's return back up the stack. So this way we can actually stream data out to the client and not have our headers get all messed up. So this is cool, but what can we do with this? Like why should we be excited about this particular thing? I'm excited about this from a Rails internal's perspective. And I'll show you why. The reason I'm excited is because I want to be able to do streaming ERB. We can do this today, but it's kind of hacks. And I'm going to show you how we can accomplish this with an IO object. And the way we can discover how to do this is if we take a look at ERB, we can create a new ERB template here and we can actually look at the source of the ERB template. This is how you do it. Doc.source will show you the source. And this is what the source looks like. This is our ERB template compiled down. And you can see we have a string there. We can catinate to the string and we set some encoding on it and we're done. But we can actually subclass the ERB template and set the output variable to be whatever we want to. And the method name to be whatever we want to. So we don't have to use concat and we don't have to use a string. Which means that this code will turn our ERB template into this. Standard out.write whatever, right? And now we're actually writing to a stream. We run this program and boom, we see output on standard out. And the reason I like this approach is because we can say, okay, well, we can change the IO object to anything we want. As long as it quacks like an IO object. Which means that we can choose streaming or buffering depending on the IO object. Our code path stays exactly the same. Whereas today, if you look at the source code today, we actually have two distinct code paths. One for doing our normal template rendering and the other one for if you say like render streaming true. It's like two completely different code paths. If we actually had ERB templates that did streaming, we could just make this decision based on the type of IO object that we have. And we don't have to have multiple code paths. The other reason I'm excited about this is for use from web applications. An obvious use for this is infinite streams. But I don't think that that's the most interesting use case for using IO objects on the response stream. I think the most interesting use case is server-scent events. Now, a server-scent event, this is what a server-scent event response looks like. This is the, like if we telnet it in and took a look at the response, this is what it looks like. Now, you can see the content type there is text event stream. And each chunk of the event, each event has an optional name. So this one's name's ping. And then we have a data payload, which can be anything. But most people just do a JSON encoded, like whatever. Just encode your stuff as JSON and put that in the payload. Now, on the client side of this, we, in the JavaScript that's executed on the client side, we say, okay, we create a new event source. And this is, okay, the arrow's off. Thank you, resizing, awesome. Anyway, it's there, that slash control, that is our event source. And that makes our quest to the server, and that's where our server-scent events come from. Now we were listening for, man, yeah, keynote, whew. Anyway, so reload is the name of the event that we're looking for. And every time we get that event, this function gets executed. And in this particular case, we're just reloading the web page, right? Now with this, with this JavaScript, we can actually do real-time browser communication. My God, it's too small, that sucks. We'll zoom in. This is a demo of doing some real-time, real-time communication with the browser. So we're loading a page here, this is our user's page, my user's page. And hopefully I'll zoom in on this, please. Well, okay, yes. We're changing the file, and you can see when we change the file, the page gets automatically reloaded. So cool, we can see that reloading, and I'm a CSS master. I'm totally changing the CSS there. Look at these styles, beautiful. It's why I'm paid the big bucks, it's beautiful. Now the other thing I'm gonna demo here is we're like, I'm opening up the Rails console there, and I'm actually creating a user. I know this is small, so I'm going to describe it. I create a user, and you'll see when the user is created, the page reloads. And we actually have a new user listed there on the page. So it's automatically reloading when we manipulate the database. So how does this magic work? The magic in this particular application works this way. We have web server, which is Puma, FS events, watches our file system, and these are running in the same process. When FS events notices that our file system changed, it tells the browser. We send a message down to the browser. The way that I did the database manipulation side is that the server actually starts up a DRB server inside the same process as the web server. Our console connects to the DRB server over a socket, a well-known, just some well-known port. And then anytime we manipulate the database, we send a message up to DRB saying, hey, we did something. And then that sends a message down to the browser, and the browser can reload. So this is how we can do inter-process communication and send events to the browser that way. So I told you we would talk about Salami, so let's do that. Real-time Salami. I've actually built a Salami monitoring system for my box. On the left there is a Beagle board. On the right is a TI launch pad. It's similar to what is the other one? I can't remember. Arduino, it's similar to an Arduino. That actually pulls the data. I have a sensor mounted inside the box that pulls data off the sensor, and then posts to a website, and I actually broadcast the data. And the way that I do that is I have an observer sitting in process. I'm using a threaded web server. The Salami posts to the create action here, and then that sends a message to the observer. The observer notifies any browsers that are sitting on any threads, sitting on the index, and they're able to update. So I actually have a message bus that's built on top of observable from standard library, and when a browser hits the index page, we just add an observer. And every time the observer fires, that code block is executed, and we add an event to the queue. And then the queue is consumed inside the main thread, and that is written out to the response. Our publisher is much more simple. Our publisher just adds our JSON data onto the message bus. Just publishes to the message bus, and then everybody else is notified. And this is really cool, except that we don't have any feedback. So I wanted to have feedback, and the way I did that was I integrated G charts and SSEs, so whenever I got a notification, it would update my chart. So now we can see I have a chart of my, this is like my danger room. Have it on a monitor, I'm like, okay, what is the humidity of my box today? That top blue line is the humidity, and the bottom red line, that's actually my temperature. This isn't an actual graph of my Salami box, I was actually just blowing on it because, it's not like the Salami box isn't actually that interesting. That graph isn't actually that fun. So, okay, my God, I've only done 110 slides. Hacker stuff, we're good, I actually got 20 minutes. We're doing good, okay, great. All right, hacker stuff, yes, hacker stuff. We're gonna talk about the Ruby VM. So we're gonna talk about the Ruby virtual machine a bit, and then we're gonna talk about detrace stuff, and then I think we'll finish up. The Ruby virtual machine is stack based, and any of you that have used an HP calculator, like I used in high school, will be familiar with stack based, stack based virtual machines. I actually loved using an HP calculator in school because people will be like, hey, can I borrow your calculator? And I'd be like, yeah, totally. And then they'd be like, well, how do you, I don't understand how you add numbers, it doesn't work. And then I'm like, well, you just do two, enter five plus. And they're like, I have no idea, have your calculator back. And I'm like, thanks. So anyway, I thought that the best way to demo a stack based virtual machine would be with PostScript. So this is the GhostScript interactive console, and PostScript is all stack based. So we start out, the right hand side is our stack, and the left hand side is actually the GhostScript REPL. So we do two, and then we hit enter, and when we hit enter, two is pushed onto the stack. We hit three, and then we hit enter, and three is pushed onto the stack. And then we run add, we say add, and then that pops off the stack and adds those two values together. Stack just displays the stack, and then pop, pops a value off the stack. So if we actually want to get access to the byte code that's written in Ruby, well, we just use the Ruby VM instruction sequence, this code here. We say, okay, this actually compiles it down. So is on the left hand side is our compiled instruction sequence, and we can disassemble it by saying puts is.disasm, and that will show us the instruction sequences. And I have more messed up arrows. On the left side is the instruction names, and on the right side is the parameters to those instruction names. But we read those names, and you're just immediately, you're just thinking to yourself, what does it mean? And it's easy to figure out what it means. You just go into the Ruby source code and find this file, insns.def. It has all of the byte code written out and documentation above each of the byte code names. It's actually very simple to read. You just read the dot, all of them are documented. You just look for the byte code that you want to know about, and then read the documentation there, and it's actually very easy to understand. So the byte code that we're dealing with in this example is trace, put object, opt plus, and leave. Trace is for set trace func. I don't know if you guys have looked at this, but it's like basically you can get events of what's happening in your machine, you register a function. Put object just pushes onto the stack, opt plus actually does the addition, and then leaves that particular scope. So we're gonna take a slight detour, a little bit of a slight detour that may or may not be related to what we're looking at. We can actually translate these to PostScript. So on the left side is our function, this is PostScript. On the left side is our function definition. On the right side is the actual function code itself. So we're defining trace, put object, opt plus, and leave. Which means that we define that in GoScript, and we can actually run the Ruby byte code in PostScript here. So that is a translation of the Ruby byte code, and we can get access to the Ruby byte code in Ruby, manipulate it, and then translate it into something that we can run in PostScript. So what does this mean? 2013, print Ruby. Okay, I'm telling you now, 2013, print Ruby. And the thing that's awesome about this is massively distributed. You can distribute this out to all of your printers everywhere. Everywhere. People will be like, why can't I print anything? And you'll be like, listen, man, it's the cloud. The cloud of printers. Look, you don't need to print anything. This is the future of distributed computing. So yes, exactly. Take that, Node.js. I've actually been studying Node.js lately, and I discovered that the only important languages are CEC++, JavaScript, and PostScript, in fact. Sorry, that wasn't a slight detour. It was a massive detour, I apologize. So let's actually, let's go to our actual slight detour, which is, this is the actual slight detour. We can get our instruction sequences by calling 2A. So this gives us, this gives us access to the instruction sequences. Don't read this, you don't need to. You can just see, here are our instruction sequences. It's cool, we can do that with that object. We can eval these instructions by just calling eval, so that runs them. And the other thing we can do is, eval, there we go. That runs them, and the other thing, we can't do this. We can't load instructions, that sucks. So we can't come up with our own, we can't come up with our own instruction sequences and load them. Can't do it, or can we? If you go take a look at icquents.dev, more messed up arrows. Anyway, if you go look at icquents.dev, you'll see that there's a load that's commented out, and a function pointer there, ics.load. And we can actually get access to that via Ruby standard library with dl. So this, don't read this, don't bother, I'm going to describe it. What we do is we say, okay, well, let's get a handle to the, those arrows were totally helpful, weren't they? Anyway, we get a handle to the shared library and we look up that function. We can get the address of the function and we can create a pointer to that function. And then we can actually call that function using ffi from ruby. Which means that we can monkey patch a load onto the instruction sequence and actually eval new instructions. I'm sure Koichi is getting upset with me right now, I'm sorry. So now we can say, okay, let's compile some sequences and then load them and then eval them. So we can actually take a sequence, copy it over to a new one and eval, which means that we can go in and do manipulations on the instruction sequences and then load them. So this changes all of our, this particular code changes all of our numbers to tens. So we'll do all of our calculations, just, all right, we change it all to tens, boom, eval, that's all we need, we're done. So I highly recommend this technique for when your code is a little too readable, or when meta just isn't meta enough. And the final thing that I recommend this for is if you really need to take your app from low scale to raffle scale, like this is, this is it. The other thing, this works on every Ruby, I personally guarantee it. What? I am not lying. No, I'm not lying. Okay, let's have a talk about this later, okay buddy? Anyway, what else can we do with this? Those are some fun hacks, but what else can we do with it? We can do some micro-optimizations, okay? So the first thing that we can do is these micro-optimizations and hopefully you guys don't know about this, I hope. The first thing we can do is we can do some benchmarks. We'll have some benchmarks, like we find a slow bit in our code. A friend of mine from GitHub says, hey, Aaron, Rails is super slow, why is it slow? This thing is slow, and I'm like, I don't know, I'll take a look at it, and he sends me a test case. And this is the test case that he sent me. So I'm like, okay, let's take a look, ah, the graph, useless. All right, one side of this graph is Errol and the other side of it is MySQL2. And actually, if we were able to look at the top of the graph, the top of the graph would be ActiveRecordRelation. And if we look at these, we can see we're spending a lot of time in Errol. And quick PSA, ActiveRecordRelation, is not Errol. And the way that this works inside of ActiveRecord is, let's say, if you do user.star.food.bar.count, all the red objects there, all those red boxes, those are ActiveRelation instances. So we create new ActiveRelation, Active, the instance, and then SQLAST, and then we actually query the database. And these ActiveRecordRelation objects are actually trees. And the AST is a tree, so we're actually building a tree to build a tree. And when I realized that, I was like, yo, dog, awesome, two trees. Why do we have two trees, if you wanna know, ask me later. So here's this awesome graph again. Anyway, you saw this. Let's take a look at the code. So I wanted to speed up the Errol code, and I'm like, okay, well, let's take a look at it. Spending a lot of time in here, and this is a sample of the code. This is what it looks like. And if you look at this, you wonder, I was like, well, okay. Spending a lot of time in GC, and we're actually creating a lot of objects here. How many objects are we creating? How many strings are we creating? All of you pick a number inside of your head of how many strings we're creating, I will tell you the answer here. I'm not gonna give you a quiz like Koichi's quiz. It's not a trick quiz. Just think about it. There are six strings created, and those arrows are completely unhelpful. But where they are created here is this string literal creates, that string literal, the select creates a string object. Doing that middle interpolation there, that creates a string object. You'll see there's a little space after the interpolation. That's another string object. And all of those get joined together, which makes another string object. Evaluating that blank string there in the join, that creates a string object. And actually joining all of them together is another string object. So this function is actually creating six string objects. So if we run this, if we put this into the Ruby virtual machine compiler, and look at the instruction sequences, we can see, okay, these are the instruction sequences. This is the instruction sequence for the string literal selected. We'll see that it says put string. And if we go look at the source for put string, we'll eventually find that it calls this rbster resurrect. And you can see there it's clearly calling string alloc, which is allocating a string. It's easy to prove that these string literals are actually creating new string objects, we can just loop over them and call object ID. And you can see there clearly, clearly these are new string objects. All of the IDs are different. Now if we look at the interpolation, we see this. That first one there, that from, that's a put object. And then down there we're starting to call a method. And then you see we call put string on that space, line 25 there. And then we call can cat strings. These arrows are probably not gonna, wow, huh, that one lined up, cool. Anyway, so if we go look at put object, we can see, well, it does nothing. Awesome, we're not creating any objects, we're just putting an object onto the stack. That's great. So the long and short of it is when we have an interpolation like this, and these arrows don't totally suck. We get a put object here, put string here, put string here, and then finally it can cat string. So all of those strings in the middle actually create new string objects that just get thrown away. They can never be manipulated but they're just thrown away. Though I have to say this, I was preparing these slides and I'm like, it's not lining up. I don't see, I saw this problem before. I saw this problem before, why isn't it happening? Well, it turns out it is fixed in 2.0. Thank you, Koichi-san. So now in 2.0, this is put objects, put objects, put objects, and finally it can cat string. So doing string interpolation in Ruby 2.0 will only result in one string being allocated. So step four, I updated the code and the way that I did this is, I changed some of these string literals to be constants. And we can do that because, well, we're never manipulating those constants. Inside that function, we're never actually mutating them. And all of those are just going to result in a put object. Let me just call it put object. So I changed a lot of those to be constants. And then I started using string append. And now our string allocations are only there and there. So we reduced it from six string allocations down to two. And running this particular benchmark with Rails, I found that we had an 18% reduction in GC invocations. And actually an 18% reduction in GC time, which is pretty nice. But I have to say, please, please, please, please, please, optimize for readability first. Like looking at all these string incatenations and these crazy, like constants floating around in there, you can tell it's been raffle scaled, but it's totally hard to read. So find your bottlenecks, optimize for readability first, then find your bottlenecks, then change your code. So the next thing I want to look at is detrace. We only have seven minutes and like 70 slides. Okay, I need to speed up. So detrace is a tool for monitoring our processes. This is what a D probe looks like. So the top there, we specify the function that we want to monitor. That second line, we specify a predicate so we can say like only fire this probe during these particular, I don't know, in this particular condition, then we execute this decode. And the Ruby probes that we have, or that I have added, these are too long, but I would like, this is too long, but I have divided them into seconds. We have function probes, things for, things for monitoring the functions that you call in your Ruby codes. You can say like, oh, this method's called, this method's called, or returned, object creations, object creation probes, GC actions, and Ruby internal stuff. So like this one's looking at the virtual machine itself. So I want to take this and I want to take these tools and use them to inspect Rails boot time. And I have to say like, there's no really incredible, like no revelations in this particular section. We're just going to study it. I want to look at how we use D to study these. And we can take this, like, we're going to look at how to use D basically, detrace. The first thing, first example we're going to do is count the instruction sequences that are executed. So this is the script that we're using. This is my test script that I'm using throughout all of these examples. All this does is load the Rails environment, which means load up bundler, initialize your application, and then we exit. So all I'm really doing here is profiling app boot time. And when we run this, when we run this decode, we find out, well, the number one opcode that's being executed is the trace opcode. And the trace opcode is the one that does set trace fun. And I'm like, well, wow, that's our number one opcode. Why don't we disable it? There's a way to disable it. You can set the compile options globally on the Ruby virtual machine, and this actually removes the trace instructions. And also this particular function works on every Ruby guaranteed, I promise. It's my seal of approval. Ah, resize that, it says seal of approval. Oh well. No, I'm not. Yes, you are. No, I'm not. So we run it again and we see the output here. Get local, now get local is our top one. We don't have trace anymore. Trace is gone. Now the question is, is this faster? Is it faster? We got rid of the trace instruction and is our app boot time any faster? So I took 100 samples of loading config environment and then I did a little statistics on it and found that our mean time, the top one, that's our mean time with the trace instruction. And the bottom one is our mean time without the trace instruction. So it looks like it might be possibly slightly faster, but then when we look at the standard deviation, we see the standard deviation is like 0.05 seconds, right? So this basically means no. It's not faster at all. We didn't do anything. So eliminating the top instruction didn't save us any time. The next thing we wanna look at is, well what is our favorite instruction? What instruction are we spending the most time in? Like where are we spending most of our time in the Ruby virtual machine? And the way we can do this is we can set up a timer in D. So this top probe, all this does is execute this code every 5,000 hertz. So every 5,000 hertz on your machine, it does a sample. This bottom one just says okay, anytime we run a Ruby instruction, save it off, right? We just save off the Ruby instruction. And then this timer, this timer says what instruction was just executed, count them up. So we're taking a sample, we're taking a sample of the instructions that are being run. So when we look at that and we get this count, this count doesn't actually really mean anything except that they're relative to each other. So we know that when we're sampling the process, we're most likely to be inside of a send instruction. This actually shouldn't be surprising to you if you were in Koichi's talk yesterday. So if you wanna look at how to find where to speed up the Ruby VM, that send instruction is where we need to go. If we can speed up the send instruction, then we're really going to speed up the Ruby VM. And if we looked at this, if we looked at the entire sample for this, we would see that trace, yep, the arrow is totally messed up. But trace is like way up there at the top. We're spending like basically zero time in trace. The next thing I took a look at was GC time. Shoot three minutes and 30 slides. Okay, GC time. We can measure GC time, measure the marks. When we mark, when we sweep, and then total up that time and look at the total time for our process. Ah man, come on. So when we look at that, we can see like, well, okay, we're spending 24% of our time in the garbage collector when we boot Rails. The next thing I went and looked at was compile time. Oh, all these times are going to be in nanoseconds unless I say otherwise. So then we look at compile time. So we can monitor our compile time and this is actually parsing the code and compiling it. So this is actually reading the file, turning it into instruction sequences. So that's the amount of time, that's what this is measuring. And when we look at that, we're spending about 21% of our time doing compilations. And this is with the garbage collector disabled because we can collect garbage during compile time. So I disabled the GC. We're spending about 21% of our time in compile time. And the next thing I want to look at is searching. And what I mean by searching is when you say like require foo, we actually have to go search, okay, we go search loaded features. Ruby says, hey, have you required this file already? If you've required it, then we need to exit. If you haven't required it yet, then we need to figure out where this file is. So this particular probe wraps that function. It says, okay, we're going to calculate how much time Ruby spends searching for your file. So this particular one prints out the timestamp that we search and the amount of time that it took to search for that particular file and the file that we were searching for. So the statistics on this are when I ran this benchmark, again with GC disabled, I found that 30% of the boot time in this Rails app was just searching for files. This wasn't requiring them doing GCs or anything. This was literally trying to find the files on your file system. This app had, what, 1600 files, 1650 files. If we graph it, man, the graph is tiny, that sucks. So that's what the graph looked like and I thought, well, okay, maybe it's linear growth. I don't know the equation or I don't know the algorithm for finding these files and I think, well, maybe it's linear. So I did a linear fit on this and found that, well, okay, this is actually what our graph looks like and these numbers are in nanoseconds, right? So our coefficient there is only 174 nanoseconds. So as we're going along in time, we only increase 174 nanoseconds. This is basically flat, that's like nothing. I don't even know what 174 nanoseconds is. So crap, 45 minutes, but you gotta see this. Okay, bug 7158, somebody filed a bug saying requires too slow. I think it's too slow. 30% of app boot should not be a file require. They attached some patches and there have been some back and forth so I decided to apply the patch and measure the amount of time. I did that same test, 16% of the boot time was now searching for files. These are graphs comparing them. The graph on the left hand side is our total program time, how much it took to boot the application. The one on the right is how much time we were spending in search. This graph is, the black is how much time we were spending before the patch. The green is how much time we were spending after the patch and if we actually sort the times we can see the red line there at the bottom is the times after the patch, the black line is before the patch. So we can actually see a drastic difference in the time it takes for searching required files. Now if we actually run the process itself we can see okay, that top one took about 1.5 seconds and the bottom one took about 1.1 so we saved about 0.4 seconds. Now if we combine all these graphs together we can see before that particular patch we're spending 30% of our time finding the files. The rest of our time, that 25%, that could be in the Ruby virtual machine. So even though Koichi did those awesome, those awesome speed improvements for the virtual machine we're not seeing any of that benefit on boot time because that percentage is so small. Now after this particular patch is applied we're only spending 16% of our time in fine files so now during boot time those VM optimizations actually help us. So this particular ticket I love it and I hope that this patch gets applied. So I wanna end this talk with some of my very favorite yearbook phrases, stay cool, never change. But really I wanted to end this with work, eat, hack, try Ruby 2.0 and I'll see you all next year. Thank you.