 So, this talk is about Event Machine. I'm going to cover a lot of code, a lot of different stuff. So, if you have questions at any point, feel free to ask. If something's unclear, just interrupt me and let me know. So, about me, my name is Amon. I live in San Francisco. I've been maintaining Event Machine for 18 months now. I was responsible for the last four releases. There's another release coming up in probably the next two weeks. I work on a bunch of other projects. Mostly, lately it's been performance and debugging stuff for MRI. And you can follow me on GitHub and Twitter. So, what is Event Machine? I'm curious, how many people have heard of Event Machine? And how many of those people have actually used Event Machine? Okay. So, Event Machine is an implementation of the reactor pattern. It's similar to Python's Twisted project. Event Machine currently supports a bunch of Ruby VMs, including 1.8.1.9 and Rubinus. And all three of these use the C++ reactor. We also support JRuby, which has its own Java reactor. In addition, we have a simple pure Ruby version of the reactor that kind of sort of works. Not many people use it and doesn't have all the features that the other reactors do. So, who uses Event Machine? A lot of people use Event Machine. It's in heavy production use in hundreds, if not thousands, of reactors. It's definitely production tested, very stable. And if you're trying to do some of the things we're about to talk about, Event Machine is definitely something you should look at. So, this talk is about IO. What is IO? IO, for us, usually refers to network IO. So, this includes basically talking network services like MySQL, HP, Memcache, stuff like that. And in the context of web applications, these web applications are IO bound. They are not CPU bound. It's not common that you were writing a Ruby web application that is generating fractals, although we did see that today. So, the basic idea behind EM is that instead of waiting for IO, instead of waiting for MySQL response or instead of waiting for some data to be returned from an HP request you made, you can use that time to do other stuff. And we're going to dig into this a little bit more. So, that's basically what EM is really good at. It's really good at scaling IO heavy applications. And EM can easily, in production, handle five to ten thousand concurrent connections with just one single Ruby process. And this applies to really any type of network IO. You can be sending emails, making HP requests. You can even write your own custom TCP proxies. People have done that, written proxies in front of MySQL or Memcache. And a lot of times people will use it to do data access since data access usually ends up being pretty slow when you're doing expressive queries against MySQL, for instance. So, let's just talk about how you do IO and Ruby with that event machine. There's a bunch of APIs. There's TCP socket and server, which is kind of expected. So, here's actually the class hierarchy of what the IO classes look like in Ruby in this. And you'll notice in here there's a class socket that's actually not the superclass of TCP socket. It's actually just its own little thing. It's kind of weird, and it actually should probably be called raw socket or something, but that provides a raw access to the BSD socket API. That's something that you would be using if you were writing C code to do these similar sort of things. You could take C code and translate it directly to the socket API. And that's what code usually looks like when you do this. And you'll see there's a lot of code. You're creating a socket, but you're also creating a test, and you have to tell the socket to connect to that address. This is not something you would usually do, but if you were writing C code, that's pretty much what it would look like. So, using the higher level APIs, say you wanted to write a very simple TCP server. You can do this pretty simply in a few lines of code. So, you start up a TCP server. That's an object, and you can accept new connections off of that socket. So, basically anytime somebody connects, except it's going to return that new client. And then that client is its own TCP socket that you can use to read and write data from that client. And the important thing to notice here is that anytime you call a read function or even a write function on a socket, it's going to be a blocking call. And so what this means in this context over here is that you can only handle one client at a time because you're sitting here, if you see the code is calling client.readline, and until that client sends you a line, you're basically going to be sitting there just waiting. And even if someone else starts to connect, they're going to be unable to connect. So a common solution to this problem is to use a thread per client. And it's pretty easy to make that change. You just wrap the server except in a thread. And so every new client that comes in, you spawn off a thread for. This is cool, but it's not really a great way to scale. And what we're going to talk about is basically the alternative to doing this, which is non-blocking IO. So this is the alternative to having threads for each client. And the basic idea is instead of blocking, instead of waiting in the read call, you just never block. And you can notice that this non-blocking version is way longer, it's way more complex. There's a whole bunch of stuff going on. I'm going to point out a couple things. First of all, you have to keep a list of clients. There's a whole bunch of buffering going on. And so basically the way this works is you have a list of clients and you pass this list into an API called IO.select. And IO.select will basically watch those clients and when some of them become readable or writable, return to you an array of ones that are readable and an array of ones that are writable. And then once it's returned, you can basically loop over those and process them as you want. You'll also notice, it's probably pretty hard to read, but instead of calling read or read line, we're calling read non-block. So there's non-blocking versions of all these API functions. And that basically returns to whatever is available. Maybe we're passing in 1024 as max size, but maybe only one byte was available. Whatever is available, you're going to get returned. And so what this means is you actually have to do some buffering. So in our previous example, we were waiting on a line. You don't know how much data you're going to get, so you have to make sure you actually got a full line before processing it. So this is what EM does. EM does non-blocking IO. And it basically takes, this is the exact same thing, it's just the EM version of it. And it takes care of all that sort of boilerplate low level stuff for you. So you don't have to worry about it. The code that you write is basically the code that handles, in this case, parsing out a line and responding. So EM does a lot of other stuff behind the scenes that basically manages all those inbound and outbound buffers for maximal throughput. It does efficient IO with those buffers using some syscalls if they're available. And it has e-poll and KQ support, which we'll talk about in a little bit. So you might be wondering what is a reactor? And this is something that trips up people a lot. So a reactor, very simply put, is just a single threaded Y loop. And that's all it is. And it's commonly referred to as a reactor loop. And so here's some Ruby Studio code that would describe a very simple reactor. As long as the reactor is running, you just keep iterating. And this reactor has timers. So if there's expired timers, you go ahead and process them. If there's a new network IO, you go ahead and process that. So the whole point here is that your code, the code that you are writing, is simply reacting to incoming events. That's why it's a reactor. And an important thing to notice here is that if you write some code in your event, a handler that takes too long, that's going to impact when other events fire. Because the longer you take, the longer other events have to wait to be able to process. There's a big lesson here, and this is something we're going to come back to over and over again, is that when you're in a reactor-based system, you can never block the reactor. And so what this means is a lot of common APIs that you might be used to as a Ruby developer, you cannot use. So you can't sleep. If, for instance, you start sleeping with an Y loop, it's going to block that loop. And nothing else inside that loop can happen. Similarly, if you're doing a lot of work, like batched up work, if you're trying to iterate over something that's something that's going to block and not allow other things to happen. Blocking IO and polling, similar sort of things. MySQL queries, for instance, can take a long amount of time. And if you're waiting on a five-second query, that means there's five seconds that no one can connect to your server and do other stuff that they need to. So just to demonstrate that point again, like you're inside a reactor loop, and then if within that loop in your processing code you start up your own Y loop, that just means like the outer loop is essentially blocked and nothing else can happen. So reactor events are handled asynchronously, and this is something you'll hear a lot when you're talking about a vet machine or reactor-based system is this word asynchronous. So I just want to sort of make a distinction and show what asynchronous Ruby code looks like versus what code that you're normally used to writing looks like. So synchronous Ruby code uses return values. This is something that's very sort of natural to us as Ruby developers. You call a function, returns a value, you do something with that value. Asynchronous evented code cannot use return values. So the way this works in a vet machine is you use Ruby blocks and instead of getting a return value, you pass in a block and at some point later in the future that block is going to get invoked with that return value. And this is actually different from the way that you might be used to using blocks. On the left is whenever you do looping or using numeral, you pass in the block and you're sort of used to you pass in the block, the block is going to get invoked a few times, and then code after that block is going to get invoked. But when you're dealing with asynchronous code, the block that you pass in is not invoked right away, it's sort of stored. It's going to get invoked later when the return value is actually available and you don't know when that's going to happen. So it's just something to keep in mind, we're going to cover that in more detail. So you're reacting to events, and events are actually really simple, you know. Instead of waiting for something to happen, like we said, and basically waiting and then running some code, you take that code that you're expecting to run, put it inside a proc, and then whenever that event triggers, whenever you're ready to do that, you invoke the proc. Just to show off the code, say you have a queue and you're basically waiting for something to show up on that queue, one way you might implement that in a blocking synchronous style is you're just going to sleep until the queue has something in it, and as soon as the queue has something in it, you go ahead and use it. The way you would write that as an event is to put the code that's using the queue value inside a proc and basically make that an event, and so you're saying as soon as someone pushes something onto the queue, that's when I want my proc to run. And so in this case, you're no longer blocking, it's just going to sort of an event that's going to happen whenever it's going to happen. And instead of doing a sleep and just sitting there, you can let other things happen at the same time. The problem with events, events as a concept are pretty simple, but event code can get pretty hard. The problem is, so we take the code on the left, it's doing three things in a row, it's getting a URL out of database, making an HP request, using that URL, getting a response, firing off an email using that response, and then printing something out. When you rewrite that to the evented sort of asynchronous style, you end up with these nested blocks. And this can get really hard to parse. Another thing you might notice is we can no longer use exceptions. So we can't just use begin rescue, we have to do more work, we either have to pass in an extra block that's an error handler or we have to pass in an extra field to each of these blocks, it's sort of a success or failure case. So there's sort of trade-offs either way and it's up to you as a developer to sort of understand your choices and make the choice that fits best with your application. The three things are, maybe you just actually don't need to scale. You're not expecting much traffic and your code is just fine written the way it is on the top there. There's sort of a middle ground where you could write code like that and scale using sort of a unicorn style model where you fork off multiple processes in a centralized queue or there are certain cases where you actually need to, the best thing to do is to rewrite all your code to be asynchronous so you can actually achieve really high levels of scale. There's also another solution using Event Machine with threads. This is also sort of the best of both worlds. You can run code that blocks inside threads and run all your async code inside the reactor. This caused issues but most of these issues have been fixed. We're going to come back to this but overall, threading is not really the best way to do things. It works, it definitely does work but it's still an unnecessary amount of overhead that you're introducing per client for instance if you were following the example we showed off earlier. How do you use Event Machine? Event Machine is just a gem, like I said, it works. You could even do this on a Venus or JRuby so all you have to do is gem install and require it and you can use it. It does a lot of different APIs. I'm going to breeze through a lot of these but I don't want you guys to get caught up in the details. I'm going to show off a lot of code and stuff and these slides are already up on time to bleed if you want to go back as a reference. They're actually going to be pretty useful I feel but the thing to keep in mind and the thing I want you to take away is just watch for common patterns. I'm going to point out certain things that show up over and over again and there's certain things that we do over and over again that are usually to prevent blocking the reactor and so you'll see the same patterns and just look at these code samples and just compare them to the way that you would write blocking code the way that you're used to writing code and just sort of do a compare and contrast and say this is the way I'm used to writing code but this is the way that I would have to write code if I were to make it asynchronous. So first off, how do you run the reactor? There's a simple API EventMachine.run just starts up that while loop it takes a block and as soon as the loop's up and running it's going to invoke that block. The thing to keep in mind here is it is a while loop and so if you have code after the while loop it's not going to run. It's basically going to take over your Ruby process and so you basically hand over your Ruby process to the reactor and the reactor fires events and then you handle those events and return control as fast as possible back to the reactor. So basically in this example the problem there is never going to happen. There's another simple API you can check if the reactor is running or not and finally you can stop the reactor. So in this case as soon as we stop the reactor then it's going to continue execution that puts finally actually will happen. So like we said the reactor is basically just a while loop and there's iterations of this while loop happening and so there's a few different APIs to basically manage and deal with iterations inside the reactor and the most powerful one of these is called em.nextik. Basically what this does is queue up a proc so you pass in a block or a proc and basically make sure that code will get executed on the next iteration of the reactor loop. So again we go back to this very basic rule do not block the reactor. So what this means if you're trying to do a lot of work you need to split that work up into small chunks and basically do it across multiple iterations of the reactor. So there's a common pattern that you'll see a couple times and all over EM's code base it's sort of recursive, it's not really recursive but it's a proc that schedules itself to be called in the future. So a really quick code example on the left we're doing a very simple sort of synchronous loop where we process a thousand things we call it do something a thousand times. If you rewrite this to be asynchronous basically you create a proc that does one chunk of work so it handles it calls do something once and as soon as it's called do something it's going to schedule that proc to happen on the next take again. And so you create this proc and it's going to schedule itself after it's done and then you just have to kick it off once. So you say em.next take do work once that's going to start it off it's going to do a piece of work and schedule itself over and over again as long as it needs to. So that's a common pattern there's a simple wrap around this something to keep in mind this is not something you use very often because iterations happen very very frequently so on this laptop for instance you probably will hit 30,000 iterations a second and there's not a lot of code that you actually want to be running 30,000 times a second if you run any significant amount of Ruby code that often it's just going to peg your CPU. Mostly this is useful for integrating with other reactor loops which people sometimes need to do. The tick loop is just a nicer way of doing it and it gives you a few nice APIs like you can pass in another block at the end and that just gets invoked when the tick loop stops. You can also call stop manually externally on that tick loop. This is something that you would probably end up using more often if you're trying to do this kind of work. This is an iterator API inside of that machine so it provides a bunch of stuff so let me just walk through again comparing contrasting synchronous code versus asynchronous code so when you're iterating synchronously this is the way you use your block. You pass in the block the block executes and as soon as the block is done executing it moves on to the next iteration and invokes the block again. The problem is when you're writing asynchronous code you can't do this and the reason is because you don't know that when the block ended the work that you were trying to do is actually over and so all EMI iterator does is basically just passing an extra object and you have to manually explicitly signal the next iteration so here's a simple example like we're iterating a bunch of numbers and by the time that block ends the outer block that's iterating you're not actually done because you're still expecting to wait an extra second before and the add timer is just sort of we're going to go into timers in a little bit but it's basically doing some work and a second later it's going to fire something off and so when that outer block finishes executing you're not actually done and so you have to have a way to explicitly say I'm done, move on, do something else the other really cool thing in here is that it takes a second argument and that's basically the concurrency you want and so this is a contrived example but maybe you're passing in a list of URLs and you want a concurrency of 10 and you're basically saying do 10 HTTP requests at a time and any time one of those requests finishes signal the next iteration so it's going to pick another one off the queue and do it and so you're doing 10 things at a time. Next on threading briefly I'm going to breeze through these slides you can look back to them if you're trying to mix threads in EM but basically you can run event machine in an external thread and there's common trick that you use that basically pauses the current thread until the reactor is up and running there's EM schedule which is a simple wrapper around next take but it's basically a way to ensure thread safety and so you can either run event machine thread or you can run your own code inside a thread pool that event machine provides so by default event machine does not use threads and if you want to use threads you have to invoke this special API and the way this works is you basically again passing a proc and it's going to do instead of doing that work in the main loop it's going to do it in a thread pool and you can set the size of this thread pool so timers again back to this very basic rule don't block the reactor so obviously you can't sleep and there's plenty of times that you need to basically wait some amount of time and so event machine provides different types of timers there's two basic types of timers there's single one-shot timers and there's periodic timers so the way this works again is you can just create an object that represents that timer you give it a block and it's just going to every interval that you pass in it's just going to invoke that block something again to notice in the first example there so we're actually blocking the reactor so you're telling that periodic timer run four times a second but since you're sleeping for a second there's no way that can actually fire four times a second so it's actually only going to fire once a second and it's actually going to delay other things that need to happen inside the reactor the timer objects have a whole bunch of other APIs you can cancel them and do other stuff that you might need to we know about events in the reactor and there's a couple of quick helper APIs that I'm going to go through that basically make managing events easier so the first one is callback so far we've been using this syntax but there's actually a bunch of different syntaxes that you could use to pass around sort of event handlers so you could pass a block through you could pass actually a proc object in you could pass a method through or you could say I know this object and I know there's a method on it that I need to invoke and so callback's just a very standardized interface that allows all these different types of syntaxes so basically you can use callback in your code if you're implementing event machine install code to let users pick and choose how they want to specify their event handlers so this is an important concept it's called EM deferrable it's actually really not well named because people always confuse it with EM deferrable and they're completely different concepts deferrables are actually just a way to represent events as objects so the reason this is powerful is because you can just say I have this object and it represents this event and then anybody who is interested in this event can add procs that will get fired when it either succeeds or fails and the reason this is so powerful is because you don't actually have to worry about when the event fires it's actually quite possible that it already fired in the past and deferrable will keep track of when it fired and whether or not it succeeded or failed and so maybe it already fired five minutes ago and you just found out about it and you're like I want to know when this fires and you pass in a block it's just going to say oh this already fired and fire your block right away maybe it's the opposite case and maybe it's going to fire in ten minutes in the future it just doesn't matter when that event gets triggered you'll get notification about it so deferrable is actually a module included in your own classes there's the API you basically can either succeed or fail the deferrable object and then anybody can add callbacks or airbags and you can add as many of those as you want so a way that you might use this say you have an HP request that returns a deferrable object and there's three different interested parties that want to do something as soon as there's a successful HP request so here we just pass in three different callbacks and if I debug this request I want to save the response to a file and then finally I want to fire off the next request a couple more helpers Q, so we touched on this earlier basically it provides an asynchronous Q so instead of pop returning a value it takes a block and so there's two basic cases right either the Q is empty if the Q is empty it basically stores that block away and as soon as somebody pushes it's going to invoke the block or if the Q is not empty you can invoke it right away and here again you'll notice this recursive proc technique so this basically starts off one sort of worker off of this Q and the worker just pops one item off as soon as it's done dealing with that item it's going to pop off another item and at the end you just sort of kick it off by popping off the first item and that's that one pop at the end is sort of one worker if you did that five times and five things would be happening in parallel and very similar Q is a channel the only difference here is that instead of one person getting that message a whole bunch of people can subscribe to it and get that message and you can unsubscribe and subscribe as well so we covered a bunch of helpers I'm going to now dig into actually things that you can actually use if I machine for so one common thing is dealing with sub-processes so you can actually run sub-commands without blocking so this is cool you might maybe you have a daemon running that converts images you're calling out to image magic or you're doing something like root processing whatever it is you're invoking an external process and you don't want to block you just want to get a notification when that process completes and if it was successful or not and so again very similar sort of technique instead of getting return value pass in a block and that block will get an output whatever STD out was and a status on top of EMP open which is a streaming interface instead of getting one block you basically receive data as the program is outputting data and you can sort of interact with it in real time so you'll notice here in EMP open we're passing LS handler so we're just going to touch really quickly about what these handlers are so a handler in Event Machine Land is basically either a module or a class and basically defines a bunch of methods for different events that you're trying to process so this is just an alternative to creating and passing our procs all the time you just define methods instead and this is a preferred way of doing stuff so the advantages of this are basically that the handler that you pass in gets instantiated so in the previous example the LS handler one instance of that will get instantiated for each sub process and so now that you have an instance per sub process you can start using instance variables to keep state and it also makes your code a lot cleaner so we go back to this example when I was talking about Event Machine code can be hard and asynchronous code in general can be hard and the cool thing is you can rewrite this as a handler and basically you create one method that does one very simple thing and passes along another method as sort of the callback and so the find URL passes along the next method in the chain which is the HP get method and so the code just gets a lot more readable a lot cleaner and it's a lot easier to refactor and add steps in between whereas if you were trying to add a step in the top there you would have to reformat a lot of code and indent it and it just gets really messy so networking this is what most people want to do with Event Machine and this is what it's really really good at writing network servers and clients so there's a few basic APIs start server that obviously starts with TCP servers there's connect which starts up a TCP client and then there's open datagram socket which is used for UDP UDP doesn't have a distinction between server and client everything is just a socket so the way this looks on the bottom there we're calling connect and connect can either take a Unix domain socket or a host in port and again you pass through a handler and the top there we're starting a server and again we pass through a handler and for each client that connects to the server on port 8080 one instance of client handler is going to get instantiated so these handlers are usually either modules that get mixed into EM connection or subclasses of EM connection and EM connection comes with a bunch of events and methods on it so there's basically two sets of methods they're all just methods but there's certain methods that the reactor calls to let you know stuff is happening which are called events and there's certain methods that you call to interact with the reactor so we can go through some of these these are all defined inside EM connection connection completed this is useful for clients basically you called EM connect as soon as that connection actually is successful the reactor is going to fire the connection completed handler on whatever module you passed in similarly there's received data for incoming data unbind from when the connection closes methods you can call in connection completed or posted in it you could just call start TLS and that's one method call that's all you need to enable SSL SSL is completely built in and takes care of everything for you so it's really easy to make your connections encrypted you can get the remote IP and port send data close connections there's a lot more fancy features you can easily do proxies you can pause and resume connections you can do all sorts of crazy stuff so let's go back to what we started with we started with this blocking code that's basically going to wait until it reads a new line off the socket and that's when it returns you a line that it read with non blocking code you don't have that luxury you're basically going to get whatever data was available and you don't know what's available so the thing you have to do here and we touched on this earlier is you have to create a buffer and parse out logical packets from that buffer and sort of the overriding idea behind this this is that TCP is a stream so what this means is say you have either a client or server on one end and it calls send data it sends string hello and it sends the string world when this goes over the network you don't have any guarantees about how it's going to show up on the other end because TCP is a stream and you're reading whatever data is available so on the other end it might show up like that and so it's your responsibility as as a user or as a developer to write code that parses out packets in the way that you expect them to show up so the code on the top right is a very naive way of writing a handler this is the way everybody starts out writing a handler and it doesn't work so the way you're actually supposed to write this handler again is you have to create a buffer you buffer data and then based on the protocol we're using in this case we're using a line based protocol so we're saying anytime there's a new line we know we've received a logical packet so we use slides to parse out that packet and then we go ahead and do whatever processing we want you can use there's a bunch of other helpers inside of that machine you could use there's a thing called buffer tokenizer you can pass through a new line too and it'll do this sort of thing for you buffer tokenizer is cool because you can say maybe I want to actually or maybe I want to give this crazy string that I want to separate in my packets but the basic idea is you end up writing these protocol implementations that take this raw stream of data and find logical packets based on the protocol that you're using so that machine actually contains a whole bunch of different protocols inside the protocol namespace one of the really cool ones that I like using a lot and I really recommend that you check out when you're trying to write a simple server client it's the object protocol so the way this works is all you have to do in your handler is just include object protocol and object protocol is responsible for defining receive data for you and so if you look at what it's doing it's basically defining a whole bunch of stuff it's make sure that enough data has showed up and again it's doing buffering and eventually when there's enough data it just un-martials Ruby object off of that stream and it takes that new Ruby object and invokes receive object and so basically in your handler you don't have to worry about any little details anymore instead of using send data and receive data you can now just use send object and receive object and deal directly with Ruby objects and it's going to handle all the marshaling and un-martialing for you there's a lot more protocols there's a bunch that are built in there's a bunch that the community has put up on GitHub and on Rubyforge so some simple ones that are built in we have a lot of email stuff we have a bunch of dash stomp we have a bunch of other ones external we have a really good HP request there's actually a couple built in HP protocols I don't recommend that you use them they're going to get deprecated the one that's linked on the right there is the one to use and it's really robust and it supports a lot of different features there's also very recently a whole bunch of WebSocket implementations which is really cool you can use that stuff with Chrome and the new browsers to do some pretty fancy stuff so that's networking and we touched upon Epo and KQ so I'm just going to explain this really quick we talked about in the very beginning IO.Select and Event Machine uses Select by default and Select is very portable it works well even worse on Windows but it has some limitations by default it's limited to a thousand open file descriptors so you can only handle a maximum of a thousand connections it also doesn't actually scale very well so it gets slower as you add connections to that set and this is because the way it's implemented you're basically passing the list of things you care about into the kernel every time the kernel had to copy it in and out of kernel space so the alternative to this that allows you to scale up to tens of thousands of connections is Epo and KQ Linux sets Epo, OSEX and BSD have KQ and the way it works internally is different you just register the file descriptors once upfront and then after that you just get events as they happen and so to use these in Event Machine it's really easy before you call EM.Run you just need to invoke EM.Epo or EM.KQ based on whatever platform you're on there's a lot more stuff you can do with the reactor I covered some of the major features but there's a bunch of other stuff you can actually watch files and processes so you can get notifications when a file gets deleted or moved or modified you can get notifications when a process forks off or process dies you can receive input from standard in all sorts of crazy stuff so I covered a lot of stuff you might be curious how do I actually use this in sort of a real world situation like what can I do to actually take advantage of Event Machine so there's a couple of different ways you can use Event Machine and you can write about applications you can run EM in a thread and again if you're trying to do something like that I recommend going back through these slides through the threading section, look over that the best way to do it is just to use an EM enabled web server there's a few of those now, Thin is the most popular there's also Rainbows which is sort of related to the Unicorn project but Event Machine enabled and as long as using one of these they already have an Event Machine reactor running and so in your handlers, in your models you want basically, you can just invoke any of the EM APIs that we talked about and set up timers or make HP requests or do whatever you want basically if you want to go one step further there's a really cool project called Async Sinatra that is really cool for handling streaming and delayed responses so there's some quick examples basically it just adds to the Sinatra DSL so instead of get you can do a get or a post so on the left there, if you call rsh1, it's basically not going to return anything to you until one second has elapsed and you can actually do those 5000 people could hit that URL and one second later all 5000 would get a response and you're not actually blocking anything that technique is really useful for sort of long polling and there's a more real world example on the right where you're actually making an HP request and when that response comes back is when you respond to who made the request to you so I want to show off a quick little demo I wrote a simple little chat server it's a line based protocol it covers a lot of things we talked about so there's a line based protocol in there it just uses the same buffering technique that we showed about it has just one channel it creates a channel object and so when new connections come in they all subscribe to the channel and that's how messages are distributed that's the slash say command and that uses a combination of EMQ and system so basically if you do slash say and type in some text that's going to add to a queue on my laptop and there's a recursive proc that's just sitting popping off things off that queue and calling EM system in a non-blocking fashion to invoke the say command on OSX to actually make the computer talk I also added a simple emhp request to twitter streaming api so if anybody mentions event machine or mwrc those tweets just get pipelined right into the reactor so again this you can check out this gist I'm going to I have to start this up and do some other stuff but we could try this out in a second but again in just 120 lines of code there's one reactor loop that's doing all of this stuff and it's not blocking it's able to handle a whole bunch of connections so what I did was since the internet is so bad I set up a ad hoc wireless network called mwrc event machine so if you can try connecting to that yes sorry I'm kind of confused with the multiple screens over here so the server is now up and running let me just try to figure out what IP address I'm on here's the IP address 16925443149 I think that's the same IP I have on here so what you can do is actually just open up a terminal as long as you're on this network you can tell net to port 1337 on that IP and it's a nice little chat server I'm using terminal emulation to do like colors and crazy stuff like that so if people are actually able to join they'll show up in here and I implemented a couple commands so you can change your nick let's everybody else know that you changed your nick and I can say hello yeah sorry one second there you go 16925443149 port 1337 doesn't look like anybody is able to connect so the internet is actually broken so the twitter stuff is not going to work but yeah people can join chat and then basically if I say hello then my computer is going to start talking and if you guys are able to join you can do that and make my computer say stupid things so that's basically it the code is all up here you can check it out it's actually really simple I don't know how much time I have but I could go over it real quick so I'll just show you the code and it's not very long so it's all in all it's 130 lines of code at the bottom here we're starting the reactor and we just start a server we say chat client is our handler and then at the bottom here we're connecting to the twitter stream watching for these things and anytime things come in we just parse them and send them to the chat server so in here we have a couple things we have a channel and so again you can see in here all you have to do to send a message to the chat channel is just push something onto the channel object and everybody who's subscribed gets it and there's all sorts of crazy ANSI codes in here so there's a channel, there's a queue over here again I create a queue and then there's just a simple processor that just pops the thing off the queue call system to say that message and as soon as it's finished saying that message that's another thing off the queue so there's two of those things and then there's a post in it which gets fired as soon as somebody connects and so I send them I give them a name I subscribe to the channel and I just send a header along and send some scrolling and other ANSI codes and then I let everybody know that this person joined and then unbind is when they get disconnected so I unsubscribe them from the channel and let everybody else know that they left and then the only other thing you need to do is set up your received data again I do some buffering in here nice, pull out complete lines and I just have to do a simple case statement or I can sit in here I'm just doing regex if statements so you can change your nickname it basically changes your name lets everybody know you changed your name you can say something that just pushes onto that queue and there's a processor sitting on that queue invoking commands in the background you can quit and then else whatever you said basically gets sent to everybody else with your name attached to it so I don't know if anybody was actually able to join but alright well I tried but you could just download this and run it on your own box and tell it to it locally to try it out if you're interested so that's pretty much it there's much information we have all the codes on github we hang out on IRC these slides are up on time to bleed we actually just moved the homepage over to github and we're trying to clean that up so if that's something you're interested in helping out with or if you want to help out with the next release or with documentation that's definitely something we could use some help with other than that you can find me either on IRC or twitter or github any questions yeah so you said there is a java version yep there is a j ruby reactor it works really well I actually refactor a lot of it and ported a lot of the design concepts from the C++ reactor a few months ago and I have used it in production the jvm does if you're using the latest jvm it will automatically use kq or epol based on the system you're on yes and it does all the same sort of stuff just in java code just to make sure everything is on blocking and does IO as fast as possible yeah it's part of our codebase you could actually just use the jar yourself it's sort of tied to ruby I think it maybe tries to invoke some of the ruby APIs directly but you could probably easily modify it to use it as its own little thing over here it seems like you said that you have to actually tell it to use kq yes you do have to explicitly tell it select actually works really well for most cases so unless you're actually expecting to handle a lot of traffic there's no real need to enable kq or epol the real reason it's optimal is because there was a big issue with threading and epol and we only recently fixed that and so in the future we could actually automatically detect and enable that by default but that's not something we've done yet any other questions there a lot of you talking about what performance like how does how performance is this as opposed to pythons twisted or nodejs it's very comparable they all use similar sort of techniques actually in benchmarks it's actually really hard to benchmark this kind of stuff but in sort of rudimentary benchmarks it does outperform both libEV and libEV is what node uses and the big reason for that is because a lot of the stuff is done either in Java or C++ directly and it does a lot of stuff that even libEV doesn't do like a lot of the buffering it takes care of and so as a user when you call sendData all it's doing is putting that into a buffer and the reactor actually very intelligently will try to push out that data as fast as possible you can handle connections when you're doing non-blocking IO are very cheap they're just a few bytes inside the kernel and especially with something like ePolo KQ I have done in production with one Ruby process handled 8,000 clients without breaking a sweat there's no way to handle that many of the current connections I've got a little bit older AMD hardware can serve 25,000 plus so to say something can you say that you got Ruby and you got AMD machines in Node.js or something like that Sure, Node.js actually borrows a lot of concepts and we're borrowing some of the concepts that they've innovated on and it's a similar sort of technique and it's basically the same thing it's just do you want to write Ruby code or do you want to write JavaScript the advantage in JavaScript land is people already used to writing asynchronous code and handling events in the way that I described whereas in Ruby land people are more used to writing synchronous code and so it's sort of a people tend to write code the wrong way and that's something I try to highlight in this talk is don't call sleep because that's not going to work whereas in JavaScript you can't call sleep so it's not a problem so it's just a little bit easier back there That's it already Is it possible to write files in sync with sleep? That's something that we do not support, that's something that I want to copy from Node, it's actually implemented really well there. The problem is that SELECT, EPOL and KQ don't work on DiskIO they only work on NetworkIO and so the way that Node does DiskIO is actually they have a thread pool of real kernel threads in the background that DiskIO gets passed back to and there's a library called LibEIO that Node uses and it works really well that's something we've definitely talked about bringing to that machine Anybody else? Alright, thank you