 good morning morning yeah welcome to Singapore and and welcome to the weather will become 2017 and then this is my I don't know fourth conference here I don't know fourth or fifth may I ask you a question few questions how many of you are developers almost all of them thank you how many programmers a little bit less thank you how many of you consider yourself as creators okay fine okay we fellow creators I'm going to talk about creating software and the setting goals and the result with root they accomplished those goals okay we create software in creating software what is a goal my personal goal is now related to software via good father as a father of four children so being a good father is quite simple goal right quite simple goal but sometimes it's hard to accomplish a simple goal like a being a good father but there are so many reasons to fail like a wrong priority or maybe you know show temper or something like that so there are a minimum reason to fail and then our software goal is to create great software and then simple but it's kind of hard to create great software we have to define great we have to try very hard to create the great software especially when software have become popular so we have so many burden in the history of the development of software for example we will be our simple goal is make the language better right so our we quote team there will be court team working very very very very hard to make Ruby language better but sometimes that kind of simple goal is pretty pretty difficult to accomplish because Ruby is so popular so that's the reason we have so many people here in the audience and then it has Ruby has helped so many developers all over the world in Singapore in United States in Japan of course India or Malaysia or Europe many countries so it has helped many come our developers probably more than million developers all over the world and then in it beside that Ruby has survived for 25 years like it you know it's quite rare for software project to survive more than 20 years but it you know Ruby survived 25 years so that so many software were written in Ruby so you write software in Ruby you write software in there are tons of software written in Ruby so in that sense so compatibility models for Ruby because even the slides slides change even the teeny bit of the comparably breakage would break thousands of software so we need compatibility in fact Ruby has a lot of technical debt for example so I am a mere human so in design of Ruby I made some mistakes or gadgets or something and so I sometimes I regret them so that I feel some kind of trouble so that I want to resolve those kind of troubles by breaking compatibility so the in us in the soft design of software or in design of languages so the designers sometimes want to change the language or software in better way by breaking compatibility for example we had some kind of huge breakage in between the Ruby 1.8 and Ruby 1.9 it was more than 10 years ago but it is a good thing so we replaced up we replaced the virtual machine that makes Ruby a few times faster and then we introduced some kind of multi-language things so that we can safely use the so many encodings the strings encodings like a Unicode and CIFJS in Japan or maybe in the big five in Taiwan or some some other encodings so the Ruby 1.9 and Ruby 2 supports the more than 80 encodings all over the world so that kind of change was needed but at the same time the breakage we brought stopped evolution there are so many people stay using the old 1.8 for a long long time so we need we needed more than five years to as a community to migrate toward 1.9 after we released the 1.9 so that those five years the community the at least the half of the community was slowed down in the improvement from the improvement of the language and the implementation of the runtime so the that five year is kind of waste of time for us the Python was even worse they took more than 10 years or PHP they even cancelled PHP 6 so the people who is working on the PHP so created the new whole new language without compatibility named PHP 6 but it was the gap was so huge and then no one in the community virtually no one in the community chose the PHP 6 so they just gave up the similar things happened in ECMAScript 4 so they gave up ECMAScript 4 so it's it's called second system syndrome so when we have trouble with the current system we just get mad and throw away the first version then we create the second version which is whole new and far better and no one used so we have learned we have to move on step by step gradual change is the way to go so that we have to buy a comp to accomplish the goals we shouldn't throw away our current systems current software then we have to gradually improve our systems and then we have to set up the simple goals and then we accomplish them one by one okay let me show you a case study of accomplishing the simple goal for Ruby last year two years ago actually two almost two years ago so I get give up this kind of the slogan model or key phrase to name the Ruby 3 by 3 that means that we want to make Ruby 3 three times faster no you know that may so many people inside of outside of the new Ruby community complained about the slow slowness of the Ruby language in most of the case so Ruby is fast enough there's reason you use Ruby right but you know the comparing Ruby to say C plus class or maybe Java or I don't know so and then a under the very simple micro benchmarks Ruby slow yeah the the grouping million times the empty million times empty loops you know a few hundred times slower than C plus class of course but in real-world application Ruby is not that slow but you know but but at same times no one complains about the faster Ruby you know if you we got fast so everyone's going to be happy except for except us so the faster Ruby the make Ruby faster that is the simple goal it seems straightforward and pretty simple okay making Ruby fast but technically it is difficult you know the we have been we have been working on Ruby virtual machine for last two more than 20 years so the we all we have already picked the low hanging food so we have to do something very drastically to make it make Ruby fast fast for three times so actually far more difficult than you may think because we have some kind of the human rules or maybe regulations the hard part is of course hard part is compatibility we have to keep compatibility even though the release faster the second one is the memory usage in general the software performance is that is kind of the time and space trade-off so you usually when you make your software faster your software will consume the more memory for example JR Ruby thanks to the JVM JR Ruby is faster than CRuby in most of the cases except for startup times and that's that's great great things thanks to JVM but at the same time JRuby consumes more memory in micro benchmarks it consumes a hundred hundred times more memory or it consumes a 17 more time more memory on the article benchmark which is relatively big benchmark and that's some somewhat realistic benchmark we will talk about up to get later so the but the Ruby language may run on memory type environment like a hierarchical smallest dino I happen to work for her okay so that the it is very important for me to ensure the Ruby would work work we will run safely on the smallest dino with up 520 meg of memory or a decent PC has only to have the 2 gigabyte memory okay your developers you your PC may have the 16 gig or maybe 20 24 gigs of memory but the for the more mere PC users the decent PC only has a 2 gig of memory for a few years back the 2 gigs is big memory or even in on the embedded system some people try to run Ruby software on top of the smaller computers like a Raspberry Pi or maybe the Lego Mindstorm or maybe the teeny embedded embedded board like a with one meg of memory so at least it should be configurable to use less memory that's the first rule as I'm just I'm the second rule memory usage so that we want to make Ruby faster but at least the faster Ruby can be configured to use less memory like as the current Ruby implementation this the third one third key to rules is dependency so Ruby is a long-lived project that it's it's 24 years old so I started the developing Ruby on February 24th 1993 so that in on next February Ruby will turn to 25 whoa so the depend for Ruby depending on the outside project is dangerous for for example so that to make Ruby faster so we can rely on that these projects like LLVM LiveJet GNU Lightning better we don't have control over those software so that these are the third party software and then it's you know we can we cannot control them unless you're an Apple if you're Apple you can buy them that software so that those software may have bugs so that they may not put you on priority the project may be abandoned so so that we may need to focus or we have to maintain those kind of huge third party software by ourselves which is nearly impossible so that this is kind of silly things but that very few projects survive 20 more than 20 years so that if we once we rely on the third party huge project we have to take care of we might have to take care of them in the future so the programming language lived far longer than other software like you know the fourth round was born in 54 1954 the the list was born in 58 so but those language still survives the Ruby is 24 years 24 year old and then but I assume Ruby will be survived for coming 20 years next 20 years or maybe next 50 years so the we just don't want to rely on the third party project which live you know along for shorter than the Ruby itself the also we need to have the maintainability so overall maintainability matters so because I'm my maintainable code stops evolution so the if we stop revolution so that the we as the community the gradually dies so we have to keep on moving so that the maintainability matters so these are our our you know restriction regulation and here's the rules and then we I must add some kind of the easy part to make our goals easy which is one of them is a baseline so the our baseline of three times faster is compared to Ruby 2.0 which is which was released in 2013 which is four years ago not the 24 which is released in last year so the we have done a lot of improvement during the since the Ruby 2.0 so we implemented the generational garbage collectors we added that in we have added incremental garbage collector and then last year we have added the open address hash table which is which runs faster for the hash tables and the method lookup and a lot of other improvements and then we have the last last four years we have five to ten percent improvement in performance and memory usage each year we have done a good job for last last few years so the Ruby 2.0 is faster than Ruby 2.0 then Ruby 2.0 consumes less memory slightly less memory than Ruby 2.0 so we want to include these improvements in the you know the three by three measurement so this is this is one hidden regulation which makes our goal a little bit easier okay second rule our second regulation is no micro benchmarks micro benchmarks is pretty interesting like we have the some kind of shootout games the comparing compared the performance of the languages but they only gains you know the measuring the the teeny root or you know the finding so by the searching through the binary tree is quite interesting gains but you know that now usually reflect the real-world behavior so real-world application behave differently from micro benchmarks so the in the measurement of Ruby 3.0 by 3.0 so we have to build some kind of standard benchmarks so the standard benchmarks need to be very real world with that reflects real world it they are artificial but they have to affect real-world behavior so that we introduce the two kind of new benchmarks one is the web application benchmark which on top of rails because most of people use Ruby through on top of rails right unfortunately yeah rails programmers raise your hand okay that's the reason so that that this kind of benchmark is the base of this course and then you can find your benchmark here github.com no Gibbs rails Ruby Benz so we we are having we are under the process of improving this kind of the benchmark that could be in that can be introduced very easily and you can measure the performance very easily so these kind of benchmark is done by no Gibbs which is hired by the portfolio company which hires him as a working for the improving Ruby full-time the another another benchmark is the opt the carrot benchmark opt carrot stand stands for the carrot for optimization I don't know about the other culture but it's at least in Japan carrot stand for you know tempting bite for horses you know you put the carrot on in front of the hose the like a like this the horse runs the chasing carrot so that can the horse can run very very fast so that opt the carrot try to be a carrot for Ruby 3 by 3 so it's a we pursue to improve that the performance of the other carrot benchmark so the Ruby will go going to be faster the other carrot is the nest emulator Nintendo Internet system emulator so you can play say Mario using the after carrot they try to implement I accomplish the six frame per second by you know the dynamic interpreted diversion machine so you can find out the carrot here github.com mummy after carrot the after carrot is written by this guy you scandal which is insanely genius guy so we have the hidden regulation we have the baseline of the Ruby 2.0 and we don't use the the micro benchmarks to measure Ruby 3 by 3 okay that they are all the regulations memory usage dependency the maintainability the baseline the no micro benchmarks so the Ruby 3 by 3 under these regulations how hard they are I consider Ruby 3 by 3 is nearly impossible yeah we need some kind of the fresh technology named it yeah we have the tons of other optimization to the the virtual machine but the I'm expecting jet can be a very very useful in improving the performance the jet stands for the just-in-time compilation so the some language use LLVM to implement jet like a Rubinius crystal Julia these languages use LLVM to to make these language faster so it is portable so it runs on any OS and see many OS and many CPU and then the LLVM is highly optimized the code generated by LLVM is quite quality in a highly optimized and then but the jet API sometimes changes so we have to follow these change and then the LLVM is a huge third-party software so we have the problem or anxiety of dependency we have other jet libraries like a LibJet or GNU Lightning so the these libraries are less widely used and it comes with the lesser GPL which is not fully compatible with our our license which is the BSD and then we have we also have that anxiety of dependency so we have been considering adding jet to the language for a long long time and then the only option we can could think of without these kind of our problems is that writing our own jet which is very very difficult so that we were having trouble for a long long time but only this year the other option came in and yet and it stands for MRNJet straightforward you can find the blanche with MZ here guitar VN McLaugh Ruby 3 LTL MZ Blanche it's done by the Vladimir and McLaugh did I pronounce it like who is working for red hat and then the rudder mail is also the open address hash table we have introduced last year so the MZ is a little bit different approach MZ uses LTL MZ uses the straightforward GCC or SLANG and then just M-Lang uses MZ let me explain a little bit more about that so LTL stands for the register transfer language so that it is kind of the the bytecode or the abstract instructions for abstract machine and then it's based on the register in the world of the virtual machine in implementation so there are long history of argument between the stock based internal representation and the register based internal position so the stock based IAL means the this kind things so the get local up the get local variable which is the part of the YAL instructions so that you can take the the look value of the local variable of B index into the stack then the another local variable into the stack then at the plus operation consuming two stack entries then the push the result in the in on the on top of the stock then you put the the value the stock top value to the local variable in A index that kind of things like it's kind of like a fourth in a stock based language and the register based IAL which is the okay the value of a U plus value way and the value will be into the value of C so much simpler but implemented implementation wise so the register based IAL is much much more complicated so the you know both sides have the pros and cons so there's no clear but winner in this argument and then YALF the current VM YALF stands for the yet another Ruby VM the real of stands for YALF uses stock based IAL like JDM use stock based IAL gave for your information the M Ruby the alternative implementation Ruby also uses register based IAL anyway the stock based IAL is simpler and the stock based IAL is shorter in in term of the the size of the compiled bytecode the the register based IAL creates less instructions okay the size of the code it's smaller in stock based the number of instructions are the smaller in stock register based IAL and in addition the register based IAL creates less memory traffic so you can access less memory and then register based IALs claimed to run faster so that you know there's as I said before then there's no clear winner in the stock based IAL and the register based IAL but at least for JIT purpose so that the register based IAL is easier to implement JIT on top it and then register based IAL is less a little bit easier to implement the optimization so he chose the new the virtual machine instructions on which is register based so the Vladimir replaced YALF by his RTL virtual machine which is not perfect yet but it's working and then as far as under the current implementation so his RTL virtual machine is run as fast as to fall it's not slow and then it consumes almost same memory amount as the currently virtual machine so that you know the step of the Ruby makes three times faster so that you know the same performance is not satisfied so you might feel unsatisfied by the same performance same memory footprint but important things is that you know you don't have the performance decoration and then you don't consume the baseline of the memory footprint so we have the new virtual machine with register based then he implemented JIT on top of the RTL the architecture is like this the the figure is a little bit small but fundamentally the MZ here generate C code into files then compile those C code by GCC or clang as a normal a compilation state then generate the .so file shared object file then load dynamically those SO files into Ruby to implement JIT which is which is nice idea it is not straightforward usually JIT creates the instruction in memory then called the function we generate in the memory but that he he used the file systems and then the user compilers to compile JIT files so that we in under the current implementation we generate the Yav code which is in memory then we execute those in memory Yav code right those we compile Ruby code into the Yav code then execute Yav code by the virtual machine so by MZ the baseline is you can read the Ruby code then compile Ruby code into the RTL which is the register based the virtual machine code then execute the RTL by the RTL virtual machine which is straightforward and they're quite similar to Yav but once you turn off the JIT option so MZ creates the RTL then generate C code into file from RTL then compile those C code by GCC then load compile SO file then execute that function so benefit so the we don't have no tricky dependency so GCC is independent of course GCC is the third party software but which is live far longer than Ruby the first version of Ruby in 93 was compiled by GCC so GCC is old enough beside that so that you know the compilation steps is well defined so it is it's so stable so it hasn't changed for last I don't know 30 40 years so we can rely on them to next 20 years and then those compiles are very stable and the GCC is ubiquitous you can you can have the GCC on Linux Mac Windows or maybe in the on the embedded devices so at least you can have the C compiler on so many systems the by that reason so that MZ is pretty much portable and highly optimized but we also have tricks so the point is it is so many unnecessary steps compared to the other JIT so that you have to minimize headers in the build process we create the minimized header he claims that we can cut the 90% of the Ruby headers then OPS and then he used the worker threads to create the the JIT code so the JIT compilation process is the is done by the separate threads from the the the mainline threads so that you can use the the multi core to to JIT compile so as a result default RTL is as fast as Ruby and the default RTL comes from as less memory as we have the current implementation and MZ runs far faster than you have MZ comes with more memory than you have of course and then you can do that ahead of time compile ahead of time completion so you can compile all the Ruby files into the machine code then roll them into the virtual machine to run your Ruby code in C it's not comparable to plain C code written by human but it's faster than the plain Ruby and then we can have the future of so drastic inlining which makes the compiled code even faster or maybe the weird planning about the speculative JIT which is assuming that okay this argument must be integers so you can compile these numbers as integers without any the converting back and forth with the Ruby world and C world so by using these kind of the technique and ideas the MZ can be even faster of course MZ has drawbacks which is the higher compiler cost you know the the process is the generate in C code excuse the compiler the passing C code the code generated generate from generate code from C code then the dynamic loading that SO file which is all of them are unnecessary for the usual JIT like a live using live JIT or other JIT technologies so these kind of the things the you know the burden to the performance but we they are trying he is trying to the minimal this kind of burden so overall result MZ runs far faster than YALF MZ consumes more memory than YALF as I told you okay MZ runs faster than JRuby and MZ consumes far less memory than JRuby okay under the micro benchmarks which are a lot of words okay MZ runs six times faster than Ruby 2.0 in average the MZ consumes four times more memory as a reference JRuby runs 2.5 faster than Ruby 2.0 and the JRuby consumes 200 times more memory in micro benchmarks in after care lot benchmark MZ runs 2.8 times faster and then consumes 1.16 times more memory as a reference JRuby runs 2.4 times faster than Ruby 2.0 and JRuby comes 18 times memory okay under the real-world example the the difference is not that big you know that not six time not two hundred times so the evaluation is MZ is very promising but it still have some issues we cannot replace the MZ our virtual machine by MZ yet but it's promising we need more words so we don't make any promise we don't make any promise that we might not have the Ruby MZ as a jet engine for Ruby 3 but at least we already have the implemented technology to make Ruby three times faster and then the MZ achieves the highest in our client area okay we are trying to make the other with three magics like a multi-core concurrency or type inferences okay I'm not going to talk about them today but and those simple goals have hidden rules and regulations and the limitations and they are so difficult to implement so I can now I only say that today but we have tons of work to do that to make Ruby better conclusion a complex and simple goal can be extremely difficult a lot of hidden trade-offs and regulations but it's all a way of creation we are creators right so we are trying to create something we haven't seen that does it's a it's kind of magic the software developers software development is the process of making impossible possible so at the first grant making Ruby three times fast is impossible but somehow we can do nasty things by using technologies ideas with help from genius and the community so that the difficulty and the pain are cost of the creation we know it's hard every single simple goal is hard but we have to keep trying we have to keep moving forward and then endure until we accomplish we will help you the Ruby is the way that I try to help you guys to implement great software so we can help each other so I help you you help me we ask so together we can make it and then this talk is special appreciation to Brazil and my graph happy hacking and making possible possible thank you so you mentioned that mg might be slower in some cases I'm wondering if you're planning to give some API to disable it explicitly if I know that my program may not benefit from it that it might be slower with MG than than without it yeah you have to turn on mg by explicitly so by default you can run by default it will be off and I need to turn it on explicitly or by default on express okay by default it it's the performance is the same okay got it thank you hi so I'm pardon my ignorance but so the point of jit is that you instead of interpreting the program when you run it you compile it into see into like a shared object and then you kind of execute that object on the target platform correct okay and interpret so the way it is done now works how so how do you how do you interrupt how do you run I mean I'm sorry to ask that but how do you actually run Ruby at the moment like how does the interpreted way work yeah yeah you compile the your Ruby code in in C by converting out RTL to the C code okay responding C code then compile them by the C compiler then go the load in dynamically then link into the you know replace the the implementation with the C the Ruby implemented the root method by the those kind of loaded C function so that that must just run as the method implemented in C so but that that's the just that's the jit right okay and and how does it work like at the moment we don't have jit right at the moment we have interpreted the interpret but I never understood how the actual interpretation process works like so there's Ruby code and then we have the Ruby VM yeah and you basically compile the my Ruby code into instructions for the Ruby VM yes and then the VM VM fits the one instruction okay okay okay and that's obviously slower because you have to interpret the code okay okay well now I finally understand what jit is thank you you're welcome any other questions it fundamentally same so that under the the virtual machine you have to convert back and forth and in the C structured and the Ruby data types and then in the converted C code you have to you do the same so that the cost you can remove from the virtual machine is the fetching the code and the the conditioning or something like that so that makes the control faster not the the data process itself so you have to send the method in in a dynamic way so you have to fetch the the value in dynamic way or something like that that won't change so that that is the reason so the mjit runs three times faster not a hundred times faster but time okay thank you