 So this is a link to the blog which I was talking about, which we maintain during our entire summer of code. So you can go through it once. So this is what we have an agenda today. So before starting off with Rubinius, I would like to ask you all, how many of you have ever used Rubinius? Okay, so very few. So I just hope after listening to this talk, you guys go and give a try on it. So let's get started. So Rubinius is an alternative implementation of Ruby interpreter. It started in 2006, it was started in 2006 by Evan when he realized that we need an implementation of Ruby which should be implemented mostly in Ruby. And it should be faster also because we mostly face the problem of Ruby being slow. So he implemented an architecture such that despite being written, despite most of the code is written in Ruby, it is faster. And so for example, we all use many foreign libraries while using Ruby. So those foreign libraries are implemented in some other languages. So if you find out that there's a bug or we need to implement some extra feature, so we need to write that code in that foreign library and we need to learn that language as well, which doesn't benefit Ruby at all. So what he thought was that we'll write an implementation so that it does benefit Ruby community as well. So let's dig into the internals of Rubinius. So Rubinius consists of two major components. First one is the kernel and the second one is the virtual machine. So Rubinius kernel is entirely written in Ruby and it consists of built-in classes of which all are written in Ruby. And there's a virtual machine which consists of garbage collector, jit compiler, and there's additional code for built-in classes which is written over here. So for example, there's a string class and some of the methods of string class cannot be implemented in Ruby. So those methods are kept in the virtual machine. So this figure will make it more clear. So in Rubinius, we have a mapping between a Ruby object and a C++ object. So here, as you can see, there's a string class. So some of the methods of string class are in Ruby and the rest of the methods which cannot be implemented are in C++ which are inside the VM. So there's a one-to-one mapping between the C++ object and Ruby object. So and the rest of the code is about JIT, GC, etc. So let's see how Ruby code is converted to machine code in Rubinius and how efficiently it is done. So we have a Ruby code. It is fed to the parser in Rubinius which is Melbourne parser, the same as in MRI. The parser converts the Ruby code into the AST nodes which are then compiled into Rubinius instructions and the compiler or generator over here is written entirely in Ruby again. Here we get the Rubinius instruction that the part in the dotted box is optional. So Rubinius instructions are fed to the interpreter. The interpreter interprets those instructions. So for the first time, the code is fed to the interpreter and it is executed. So JIT compilation is only done for the methods which are frequently executed. So now if we are executing some code again and again, so if Rubinius figures out that this code is getting called again and again. So it will convert it to LLVM instructions and then to machine code. Also it saves a copy of compiled code in .rbx directory in the directory where you are running your application. So second time when you try to recompile the code and if the compiled code is already present, it loads that code only. So a lot of internals we have been to. Now as a beginner when I started learning Rubinius, the best thing I found about Rubinius is that it is very easy to follow as the internals are also written in Ruby. So we can dig into the code and we can see how the basic methods are implemented. So let's see how some basic methods are implemented in Rubinius. So this is a string up case function which converts the string to uppercase. Let's see how it is implemented in Rubinius. So on the left hand side you can see the code of up case method which is written entirely in Ruby and it is quite easy to understand. What it does is if the string is empty, it just returns. If string contains some number of characters, it iterates through those characters, converts those to uppercase and returns the modified string. If the string is already in uppercase, it returns unmodified string, the same string. And on the right hand side you can see the up case function in MRI which is in C which is quite difficult to understand due to a lot of macros and low level encoding done. So here it was comparatively easy to learn Ruby internals. So here as we can see there are two variables which I have not told about. Those are number of bytes and data. So let's see how is the string implemented in Rubinius. So this string contained data and number of bytes. So data is stored in Rubinius in byte array itself. So you can drill down and you can understand the internals in Rubinius because they are written in Ruby itself. So we'll also understand the implementation of array shift method whose implementation contains some methods which are not written in Ruby but in C++. As I said some of the methods are implemented in C++ as well. So what this function does is it works like a queue. If you pass a parameter to shift, it pops out those many elements from the start. And if you don't pass parameter, then it just pops out one element. So this is the implementation of array shift method. And this you can see the method tuple.at which is implemented in C++. But since this code is in Ruby, you can go there and you can put some debugging code over there to see how the underlying method works. So I have put here start total and I have inspected the tuple what it contains before and after implementing, after removing the element. So initially I had 1, 2, 3, 4, 5, 6, 6 elements. So before removing first element, I printed the tuple. And after removing the first element, I again printed the tuple which consists of nil. As you can see over here at line number, sorry, tuple.put start comma nil. So it puts a nil at the start pointer, at the start position. So yeah, this is one of the most important features in Rubinius, back traces. When we work on Ruby code, we normally come across many back traces and those are really helpful in debugging our code and finding out where the problem is. So here what I have done is I have a string and I am replacing the character at first position by nil which is not allowed because it cannot be converted to string. So this is the back trace which we get in MRI. So it just tells us that no implicit conversion of nil into string and it just gives you location of the location of where the method has been called, where that error happened. So and this is the back trace in Rubinius which tells you exactly when you have called that method, it gives you insights into all the methods which are on the stack at the time when error had come. So here at first line of code, my error was thrown. So here it just says that there is an error at line number two. But here it gives you all the details about the functions which are getting called when you get that error inside the kernel and you can go and see how those methods have been implemented and you can put your breakpoints over there as well and debug your code. So these are the different tools which Rubinius provides. So debugger and profiler are provided by Rubinius and the return in Ruby itself. The heaped up interface is also a very good tool which Sana will be explaining about and if we get time we'll cover metrics and more as well. So over to Sana. So before I start explaining about the heaped up interface, a little background about where are heaped up used and why are they used for. So heaped up are used for memory analysis of a program or of an application. They're used in high memory usage applications where you want to find why is my application consuming so much memory, why is it getting slow or places where a particular method or a block of code is allocating a lot of objects but is not deallocating them or in short there's a memory leak and you want to find out where those memory leaks are occurring and what might be the cause of those memory leaks. So basically a heaped up is a memory snapshot of a particular process that is running at that instant of time. So when the virtual machine is running, what the heaped up would consist of, it will consist of all the objects that are there in the memory and at that instant when the heaped up was triggered. So this is how a heaped up looks like and it's in binary and it's generally in a few MBs like 200 or 300 MBs and heaped up contains a lot of information that can be utilized to help a user explore memory usage of an application. So what the heaped up tool here that I'll be talking of what it does is that it reads the memory binary heaped up, it knows how to read it and interpret it so that we get some useful information out of the binary heaped up. So that's how we obtain a binary heaped up either via the query agent or using the Rubinius VM.dump code. So I wouldn't be explaining about the query agent because the query agent has been removed from the current version of Rubinius. So here I have a sample, a very short program that can demonstrate an example where I'm allocating a lot of objects but I'm not deallocating them. So what I'm doing is I'm instantiating around 10 to the power four instances of the leaky class and I'm storing them in an leaky array and I'm not deallocating them. So that's how I take the heaped up. So the heaped up tool gives me a histogram representation of my binary heaped up. So as you can see in the histogram representation, it lists out all the classes that are there in the heaped up. How many objects of those classes are present and what is the total amount of memory those many objects are taking. So but a single heaped up isn't sufficient to figure out where my memory leak is occurring. So what we do is that we take two heaped snapshots and across those two heaped snapshots we see we list down those classes in which the number of objects are either increasing or decreasing across the two heaped up snapshots. So here we can see that in case of byte array the count has increased. Now from here we can further drill down and see per class statistics. So for example we can take, we can look inside the byte array class and we can see that what percentage of objects in that class are occupying how much bytes. So for example in this case we see that five objects which is around two percent are occupying it now bytes each. So that looks something unusual and here we can investigate further to see what my byte be happening. Gauze is a web app which allows us to see what all is there inside a heaped up. So for example in our case we have our leaky class here we can go and see what all instances are there of the leaky class. So it lists down all of the instances of a class. If you open that you'll see that that's a dump object. If you open that it will give you details like what are the, what is inside the instance variable of that class and what all objects are referring to that class, to that object. And if you go on and open the params instance variable you can further see that inside the data you have a byte array. And so that's what we're essentially doing inside that we're storing byte array. So inside the data field you can see the byte array that we stored. So this way it helps you to go down and inspect what is happening internally and you can get some idea of something unusual that might be happening somewhere. Yeah now I'll tell you about Rubinius metrics. Yeah so metrics are the most important thing which an organization needs for monitoring their applications. So Rubinius provides a very easy way to access those metrics. So there's an object in Rubinius called as Rubinius, there's a class Rubinius metrics on which there's a method called data which gives you an object which lists all the metrics. So Rubinius 2.3 onwards they have added a facility to emit those metrics directly to StatsD. StatsD is a demo which aggregates the statistics collected. So using, sorry, using this command we can set the target as StatsD so that the metrics of Rubinius will go to the statsDemon and it will collect those metrics and aggregate those and will save somewhere so that we can use them further. So what I have tried out is those metrics I have sent to StatsD then from StatsD I have stored those metrics in in FluxDB database and there's another tool called Grafana which can display graphically and it needs a source. So the source is in FluxDB over here so it will take the statistics stored by StatsD in FluxDB from in FluxDB and it will display those metrics in nice graphical format so that it helps you monitoring, it helps you in monitoring your application. So these are the metrics. It tells you the status of your garbage collector and these are some more metrics which tells you about memory usage of your application. So there are many more which you can analyze. The new features which are going to come up in Rubinius 3.0 are, as I said, JIT compiler code is written right now in C++ so that it is easy to interface with LLVM because it is written in C++ but now they'll be converting that code to Ruby as well and there's another feature coming up which is JIT planner. So like we have query planner in RDBMS so using JIT planner we'll be able to configure the decisions of JIT and as I said Rubinius stores the byte code of a particular compiled class somewhere so that it can use it if that class is again loaded so but when that class is again loaded it loads the entire code but it is not needed so what code DB will do it will store that code and will load only that part of code which is being run at that moment of time so it is it will reduce load time of your code and as she said Rubinius agent interface has been removed in current Ruby version because it will be coming up as a part of console so profiler, debugger and agent interface all three will be integrated into Rubinius console so yeah that's it.