 OK, hi there. My name is Yasser Edvers, and I'm a Ruby developer from Egypt. Everybody knows where Egypt is? OK, in case you don't know, there it is. OK, I work at eSpace. I'm a lead developer. We mainly do web development, 2.0 development, and mobile development for embedded devices. So I'm here to talk about Neverlock. OK, this language is called Herogleth language. It was used like 1,000 years ago by the ancient Egyptian people, like 7,000 years or something. And I have no idea how on earth can anyone use this to communicate. So this is the English version of the last slide. I'm going to talk about Neverlock. So what's Neverlock? OK, Neverlock simply is a non-blocking IO Ruby library that helps you execute concurrent code in a transparent way. So how do you achieve that? OK, before I talk about how do we do that with Neverlock, let me introduce to you in specific what problem are we attacking. So in Neverlock, we do provide some way to execute concurrent code that does DB and network access. And we do that without the need to change the program flow. So here's the problem. We have that piece of code that contains some blocking operations, whether they are DB codes or network operations. And we need to execute that piece of code several times. So there are like three standard ways to do that. And Neverlock is the fourth way that I'm going to talk about. So the first way to do that is using an old single thread application. You write your code in a synchronous blocking way. So let's have an explanation of this example. It's simple. We have first we require my SQL adapter. Then we initialize the count. The count is the number of times that we won't execute our block. And then we initialized one, only one. We need only one data risk connection. And then we define our block. It's a simple block. All it does that it issues a query with a select sleep, 0.1 seconds. And then it iterates over the results and do whatever it wants to do. So this is our block. And we simply code our block within a count of times loop that will execute count times. So if count is 100, this code took around 10 seconds. So the other alternative is doing this in a thread way. So we initiate a thread for each execution of that block. OK, so we did the same initialization there. The only different thing that we need to do is we initialize multiple connections, each connection to be used in single thread. And then we define our block, same as the other block in the braver slide. And then we execute our code and then account the times loop. But we need to take care of something. We need to handle the thread safety. So we need to synchronize our block to protect shared variables such as the connections array that we used to get the connections out of it. And we just execute our code in a typical way. So this code runs typically in one second because we have like 10 threads and we have like count threads that are executing simultaneously. And this code typically runs in one second. OK, the only thing we had to do, we need to take care of thread safety requirements. So we had to create a mutics and issue a synchronize on the block that we are calling. OK, the third alternative is to do that in an evented, driven way. So as you might have expected, this has to be a little bit different. Instead of just having one block to call, we now have two blocks. It's our before block. That's where we issue the asynchronous calls. And we have an after block that is our callback function. So in the before block, of course, first we create as many connections as needed. And then in our before block, we just issue a send, what's called a send query method. Send query is an asynchronous call that just sends the query to the database. And actually, this was found in the Postgre driver. Postgre has a synchronous driver for asynchronous queries. MySQL, the standard MySQL driver does not have one. So we did initiate an initiative to write a MySQL driver that supports a synchronous call. And thanks to other contributors that has done a lot of effort, we had what we called the MySQL plus adapter. So anyway, now in the event model, we issue a send query. And then we have to keep a reference with our IO objects that we'll be waiting for later. And then we have to keep reference as well as well with our connections that we will be listening at. And we'll get notified that we have data available to read. Then this is our after block or the callback function. The after block, what it does mainly is it gets the connection that has available that already and starts getting a call and get result on the connection and starts processing the results as we did in the previous example. So to be able to execute that, we have to call the counter times on the before block. So we call the asynchronous code count times. And then we must have some kind of an event cycling thing. So we need to do to either register with the something like the event machine, or we just have to maybe do an infinite loop and a select call. If you're not familiar with select call, select method takes four parameters. First parameter is a reading array of IO objects. Second parameter, a readable array, a writeable array for IO objects. Third parameter is an array of IO objects that you should be waiting for expecting errors. And fourth parameter is the et cetera. So basically, a select call is a blocking call that does not return unless either of these conditions was achieved. I mean, for example, in our case, we only passed the first parameter, which is a readable array. So unless there is a readable data at either of the sockets that are passed in this array, the call is blocking. So it will only return as long as there is data available on any of the sockets associated with the IO object in the readables array. So anyway, when this select call, whenever this array is ready to read, we get out the IO object and issues. And after call block, that's our callback. And then in the after call block that gets executed, extracts the connection, and then calls quit result and start to process the rest of our code logic. So this call typically runs in one second. What's good about this model is that it's a little bit faster than Threading model. But as you must have noticed, it's a twisted model. You have to split your code to fit into this event-driven model. So if you are about to initiate another blocking call, you have to do that in the after block, which is the callback. Same as what you do when you issue an agent's call. You issue an agent request. And then when you need to issue another one, you issue the callback or the response of the first request. And then if you need to issue another one, you need to do that in the callback of the second request and so on. So this call typically runs in one second. OK. Here's how things are done with the never block thing. Typically, when we slide what we call our fiber pool, we come to fibers shortly. Second, we don't create a bunch of connections as we did in the event on the Threading model. We have our own connection pooling mechanism. So we just get what we call a pool database connection. So that's the C variable is a connection, just one single connection that we get from our database pool connection pool. And then we define our block in a very normal way that exactly as we did in the very first example, in an all-in-one way. So we don't have to split anything. Just issue our query and then get the results. And then we run count the times. We run the call, we execute the block, our block using the call method in a count the times array. Only with a little change. We run that inside what's called a spawn method. That's what the spawn method does. It executes the block within the context of a single fiber. We'll come to fiber shortly. And all this bunch of block is executed within an event machine. So event machine will count the times. And then a single fiber that executes this very method. So typically this program runs in almost one second as well. Only that you don't need to split your code. You write it in a very straightforward way, like as you did in the threading. And also you don't get to do any threat safety handling issues, no mutixes, no or nothing. So before we get to how in detail we were able to achieve that, I'll just summarize the pros and cons of the event versus the thread model. As you might have noticed, I'm talking about Ruby. Event model versus thread model in Ruby. So event model Ruby is faster, more scalable. We have no threat safety requirements. But the only issue is it has a twisted development model, which means that you have to adjust your code to fit into this event-driven model. And it is faster than threads in Ruby, because threads in Ruby are green threads. I'm sure you're aware of that fact. And other thing is because of the whole context switching thing between threads. And it's more scalable because it consumes much less resources than threads do. Of course, threading is the other way around. It's slower, less scalable. And it has a threat safety requirement. The only thing is it has a direct development model. Never block brings the benefits of the event model only in a direct development way. So that you don't have to worry about adjusting your code to fit into the ordinary event-driven model. So it's the best of both worlds. So you have a fast code that is run concurrently, and it's scaling. You have no threat safety requirements. And you just write your code in its normal flow. So how was that possible? It's possible due to fibers. So fibers, what are fibers? Fibers are just methods. They are code teams. That you are able to use just as you are able to use threads. But you are able to resume and to pose fibers on demand. That's the code difference between threads and fibers. In a fiber, it's your duty or your responsibility to do this context switching between one fiber and the other. So you can resume a fiber, and you can yield back from the fiber and give context and give processing away from it. So this is an example of fiber as I used. First, this is a fiber block. What do you call a fiber block? This only defines a fiber. It does not run anything. So this is the fiber block. Just a simple block, x equals x, then fiber yield x, x equals 6, fiber yield x, y equals 7. This is the definition of a fiber block. So the new thing we need to know is the yield keyword and the resume keyword. So let me just start by the resume keyword. After defining the block code, on the very first code to resume method, we enter the very first entry point of the block of the fiber. So on the very first code to resume, execution is started to be at that step. So x equals 5. This is the step that's executed right away after the first resume call. Then second, fiber to yield is executed. Fiber to yield actually does two things. First of all, it returns the value that is passed as a parameter. So it returns x, just a normal return. Second, it gives away control to the very next line after the last resume method was called. So after fiber to yield x was called, execution will happen to be at this line. So we now have the return value for the resume method. It is the very same return value of the yield method, which is the parameter x that was passed. So that's why it puts f dot resume on the very first line, outputs 5. Another code to resume would resume execution back on the very first line after the last yield that was called. So that would be x equals 6. And so on. On the last code to resume in that case, that will bring us after the second yield here. And then the return value of the block is the return value of the resume function and not the parameter that was passed to the yield, because we have no yield method at the last statement. So the return value of the resume function is either the parameter that is passed within the yield method or the return of the block of the fiber after it has first executing. So the very last, the third resume statement is going to return 7. So puts f dot resume, the third one is going to output 7. Our code would raise an error, because our fiber is dead. The block has fast execution. What's great about fibers is that they can do two-way communication. We saw in the last example that we used the value that's passed in the yield method to add the return value of the resume code. But then we can use it the other way around. We can pass parameters to the resume method. And that can be used within the fiber block. So the first value that's passed to the resume method can be used as the value of the block variable, which is x. So the very first code to resume 7 would enter the first line of the fiber block with the value of x equals to 7. And then fiber dot yield 7 is executed. So that's why puts f dot resume 7, output 7. And the next step puts the f resume 6. Will happen to continue execution at the assignment of the y operation. So the next step after resume 6 is called is that we will enter back the fiber gain. And y equals 6 statement is executed. Then the next statement that is executed is fiber dot yield 6, 7, sorry, fiber 6 yield 6. That gives away control again back to the very next line after the last resume code. And that's why the, so what we did here that we were able to pass parameter among across the fiber block in and out. So we did pass a parameter the resume method which was used in the block parameter. And we were able also to use the return value of the resume method as being the parameter that's passed to the yield method. So another code to resume with the parameter of 5 would just happen to bring us back here to the next statement which is assignment of the z parameter to 6, which is the return value of this block. So sorry, to 5, which is the return value of this block. So z happens to equals 5. And then the next statement is a equals 2, which is the last statement of our block. So this will be the return value of this resume code. So it outputs 2. And of course, another code to the resume raises a fiber error. So this way, we were able to pass arguments back and forth between fiber content inside the fiber context and outside the fiber context. So we were able to do what's called the context switching. And we do pass parameter back and forth between the inside the fiber and outside the fiber. So that's why you can do two-way communication using fibers. So what's great about fibers are that they require much less resources than threads do. So for example, on this very machine, I was not able to create above 800 threads per process. It's 1000 threads per process. And that was in like seven seconds. But I was able to create above 200,000 fibers. And that's the memory usage. At the number of 1,000 threads versus 1,000 fibers, it's like 4x or something. And of course, that's what we mean by that fibers in Ruby are more scalable and more faster than threads. So what Neverblock typically uses is a combination of fibers and what's called the event machine to achieve concurrency in transparent way to the programmer so that you don't have to worry about breaking your code to fit into the event model. So it's mainly an event-based development. But only we achieve that in a transparent way by using fibers so that you don't have to split your code. You just write your code in a normal way. OK? The only thing that Neverblock requires is that the whatever I owe access that you're going to do, whether it's a network access or a DB access that you must have asynchronous codes supported within this library. For example, that's why we started supporting First We were supporting BoostGrade. We first wrote Neverblock for BoostGrade because it has an asynchronous driver for DB access. So that gives us the ability to issue asynchronous queries. And then after a lot of efforts of other people and we work with other people to get MySQL plus done, so now we support both MySQL and PostGrade. So Neverblock currently works very well with MySQL and PostGrade servers to achieve concurrent DB access. OK? Also, Neverblock supports Ruby sockets, which means that libraries like Net HTTP can actually run concurrent codes of network access using this library, OK, in transparent way as well. And then for web applications, we used ThinServer because Thin uses event-based models to dispatch its request to Rails. So we used a combination of ThinServer and made use of its event machine that ships with it only with a little notification to the event machine to be able to attach our own connections to it and the attach it. So using a combination of Thin and its built-in event machine, we were able to write web applications that were requests are processed concurrently within a single Thin server. So we have a single Thin server that's able to process multiple concurrent requests at a time. Typically, what you need to do is you have to get several instances of Thin running to serve multiple requests, OK? But that way, a single instance of a Thin server can serve multiple requests in a concurrent way thanks to the event machine that's shipped with a Thin server, OK? Also, as for Rails, Neverblock supports active records. So that's really caused the Rails applications to run concurrently in a little. And actually, you don't need to add any extra line. Of course, all you need to do is a couple of requests, OK? So Neverblock supports Rails really out of the box. Let's have a visualized example, OK? This is a Thin server with its event machine, OK? We have our final pool that's injected in the Thin server, OK? And we didn't let them vacation to how Thin server dispatched its request to Rails framework. So first, when a quest A arrives, the event machine tells the Thin server that there is a quest A that is to be processed, OK? So instead of just processing the quest in the normal way, we spawn out fiber of the fiber pool that's injected in the Thin server. And we run that request in the context of a single fiber, OK? And then each requirement of those represents a single fiber that serves a single request, OK? With those blue parts as being the non-blocking parts of the request, and the red parts being the blocking parts of the quest, so what typically happens is when a request A arrives, it starts being processed within a single fiber context, OK, until it reaches a blocking operation or ever reached a blocking operation, it yields back control to the Thin server to be able to run another request. But before you do that, you have to register your current IO connection with the event machine and do what's called the IO completion request, OK? So that the event machine later on notifies the fiber that there is data available. And so that the fiber can resume execution, OK? So after the fiber A yields control to the Thin server, Thin server starts getting a new request, which is request B, OK, start processing the non-blocking part of the quest. And then whenever it reaches a blocking part, again it registers with the event machine again and requires IO completion notification for that very connection that is associated with this request. And then at that time, the event machine fires a completion notification for the very first request A. So fiber A resumes execution at the very last point it left. And that way, we even utilize the CPU usage. The CPU usage was highly enhanced and so on. That's the basic idea, OK? So what modifications you actually need to make to your RAIS application? Just a bunch of few requires. Just you require that you never block library, you never block support for RAIS, and then you require you never block support for your server, which is Thin in that case. And then in that case with YML, you write that you are after is never block Post-Ray or never block MySQL instead of just writing the normal adaptive. OK, and there you go. That way, with a combination of a Thin server and a RAIS stack and never block libraries, you are able to achieve multiple, to serve multiple requests in a given single thread applications. That means that within a single instance of a Thin server, you can actually serve multiple requests. Some people might have wondered that if this is actually using production, yes it is. And it's used in this is one of our products. It's called MiOS. Actually MiOS, it's about some social networking where you have to share your awnings and stuff with other people and share interests with them. So before using never block, we were having like 16 instances of Thin servers. After using never block, we almost have to run like four instances. And so we reached like 75% of memory saving. OK, here's a full feature list for never block. What we currently support is we provide full support to MySQL and to Postgre, to Ruby sockets, to NetHTP libraries, to ActiveRecord. And it's also has been tested and it's working with RAIS 2.1 and of course with Thin. We do have problems with the longer server though. What we need to do later on is we might be able to provide better network support. And we have issues with RAIS 2.2 because in RAIS 2.1, we have no such thing as connection pooling, that means connection pooling. Whenever you need a connection, you create it. So typically you use just one connection throughout your application. So we introduced the concept of connection pooling in our never block. We do have our never block connection pool and now it's 2.2 ships with its own connection pool. So we just want to make sure that we really conforms with the behavior and standard of the interface of the connection pool for RAIS 2.2. We also what we need to do is to support move back ends other than the event machine, like for example a vector. And other frameworks like Merb and Ramazze, or Ramazze, I don't know how that is pronounced. We also need to support other ORM tools other than active record like DataMapper and SQL. And of course, all ideas are with us. Thanks. Any questions? Questions? No? Yeah? Does the code need to be bread safe? No. Then no. Fibers relieves you from, actually that's what's great about fibers. You don't need to worry about 3D safety at all. That's the one core difference between fibers and threads. That in threads, you actually have to do all the music things and synchronization stuff. In fibers, you don't have to do that. So whether you're using rails and never walk out the locks or using your own loopy code like we did in the very first example, you don't have to do synchronization stuff at all. Any other questions? Does all of your fibers share an address space? What? Did you fiber share an address space so that a class level variable would fiber as the same as a class level variable and another? Well, actually, yes and no. One thing with fibers that you need to take care about is sharing static variables. You must not share static variables between fibers. So what you need to do is just inject your fiber pool in whatever event machine, whatever backends you need. And then from within your fiber pool, you just do the whole context, switching things with parking parameters back and forth so that you don't want to need to share your memory space. OK, but a class variable, if you're using a class variable for a cache, then you do have to worry about the same thing, because the data would be shared back and forth. Yeah, this question is true. Any other questions? OK, thanks. Thanks all.