The Future of JRuby
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 50 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/37497 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer | ||
Production Place | Miami Beach, Florida |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
Ruby Conference 201348 / 50
2
3
7
13
15
17
18
19
28
29
35
39
44
48
49
50
00:00
Programmable read-only memoryProduct (business)BitMachine codeLine (geometry)ImplementationComputer animation
01:12
Run time (program lifecycle phase)Standard deviationSocial classCore dumpJava appletEntire functionImplementationMachine codeTable (information)Formal languageMereologyJava appletStandard deviationComputing platformLibrary (computing)Run time (program lifecycle phase)Process (computing)Computing platformComputer animation
02:08
Revision controlBitBranch (computer science)Software developerAsynchronous Transfer ModeSpring (hydrology)1 (number)Multiplication signSoftware maintenanceProjective planePoint (geometry)CASE <Informatik>MereologyDuality (mathematics)Right angleComputer animation
03:35
Branch (computer science)Multiplication signRight angleRevision controlSoftware maintenanceWordCodierung <Programmierung>Software developerDuality (mathematics)Arithmetic meanComputer animation
04:24
Java appletDrop (liquid)Modul <Datentyp>Process (computing)Computing platformMultiplication signJava appletMultiplicationAsynchronous Transfer ModeLevel (video gaming)Duality (mathematics)StatisticsSource codeBranch (computer science)Software developerMathematicsBitPoint (geometry)Goodness of fitSocket-SchnittstelleComputer animation
05:46
Einbettung <Mathematik>Java appletRun time (program lifecycle phase)Slide ruleProcess (computing)MathematicsRevision controlExtension (kinesiology)Run time (program lifecycle phase)Sound effectNumberMultiplication signPlanningLibrary (computing)Java appletField extensionMultilaterationComputer animation
06:31
Revision controlJava appletPoint (geometry)System callProcess (computing)NumberRevision controlComputer animation
07:12
Server (computing)Revision controlJava appletRevision controlMachine codeLine (geometry)Standard deviationVideo gameComputer animation
08:01
Compact spaceJava appletLibrary (computing)StatisticsStandard deviationBitMereologyRun time (program lifecycle phase)Machine codeComputer fileComputer animation
08:35
Addressing modeMultiplication signMereologyArithmetic progressionSoftware developerRun time (program lifecycle phase)Point (geometry)Computer animation
09:21
Computer configurationTelephone number mappingComputer configurationProcess (computing)Point (geometry)TranscodierungBusiness modelBitSystem callData managementComputer fileTime zoneThread (computing)Enumerated typeCodierung <Programmierung>Multiplication signComputer animation
10:50
Computing platformComputer-generated imageryDatabaseThread (computing)Computing platformMedical imagingThread (computing)Local ringLibrary (computing)CASE <Informatik>Software testingDatabaseAuthorizationAreaPhysical systemReading (process)Computer animation
11:44
CollaborationismProcess (computing)Focus (optics)Concurrency (computer science)Object (grammar)Standard deviationProcess (computing)Data structureUtility softwareDynamical systemMachine codeTheory of relativitySystem callLibrary (computing)BitSoftware developerParallel portConcurrency (computer science)Software bugThread (computing)Computer animation
12:27
Overhead (computing)AerodynamicsData structureObject (grammar)CodeCompilerCompilation albumBitSocial classNormal (geometry)Table (information)Java appletInstance (computer science)Dynamical systemObject (grammar)Variable (mathematics)Data structureMachine codeRule of inferenceMultiplication signInteractive televisionProcess (computing)Computer animation
13:25
Java appletCodeTheoryNetwork topologyIterationRun time (program lifecycle phase)19 (number)BenchmarkFluid staticsExtension (kinesiology)Series (mathematics)Process (computing)Formal languageParameter (computer programming)Type theoryMachine codeSystem callMathematical optimizationNetwork topologyLibrary (computing)Revision control1 (number)Java appletOverhead (computing)Just-in-Time-CompilerDynamical systemLine (geometry)CASE <Informatik>Computer animationDiagram
15:38
Java appletRead-only memoryImplementationSemiconductor memoryFormal languageProcess (computing)Java appletOracleSoftware bugFrame problemProduct (business)Multiplication signProjective planeComputer configurationJust-in-Time-CompilerProper mapComputer animation
16:27
OracleCompilerDirected setSoftware testingFormal languageNP-hardMereologyComplete metric spaceImplementationGoodness of fitJust-in-Time-CompilerMultiplication signNumberProof theoryFormal languageSystem callOracleBitCASE <Informatik>MereologyLibrary (computing)Front and back endsComputer animation
17:29
CompilerCodeResource allocationType theoryRepresentation (politics)Run time (program lifecycle phase)BitCompilerRepresentation (politics)Network topologyRun time (program lifecycle phase)Metropolitan area networkUniverse (mathematics)Computer architecturePoint (geometry)Reading (process)Mathematical optimizationProcess (computing)Computer animation
18:11
Data structureAbstract syntax treePhysical systemExistenceParsingCodeMathematical optimizationMathematical optimizationRun time (program lifecycle phase)Plug-in (computing)QuicksortProcess (computing)MereologyAbstract syntax treeMachine codeParsingMathematicsSeries (mathematics)Data structureSemantics (computer science)Control flowBytecodeElectric generatorSet (mathematics)Point (geometry)Abstract syntaxJava appletControl flow graph1 (number)TwitterComputer animation
19:38
Block (periodic table)Mathematical analysisSystem callFile formatAddress spaceComputer programMathematical optimizationLine (geometry)Food energyCASE <Informatik>SequelParameter (computer programming)Sign (mathematics)Compilation albumCausalityAlgebraic closureMachine codeBlock (periodic table)Computer animation
20:16
Mathematical optimizationCodeGaussian eliminationCompilerMathematical optimizationVariable (mathematics)Computer programMachine codeCompilation albumLine (geometry)WordArmMathematicsBlock (periodic table)Computer animation
20:55
Thread (computing)System callLogical constantMathematical optimizationBlock (periodic table)Overhead (computing)Block (periodic table)Line (geometry)SequelMachine codeVariable (mathematics)QuicksortAlgebraic closureMathematicsOverhead (computing)Gaussian eliminationMathematical optimizationPoint (geometry)CompilerRight angleData miningComputer animation
22:17
Concurrency (computer science)Thread (computing)Parallel computingSingle-precision floating-point formatReal numberBefehlsprozessorInstance (computer science)Core dumpMultiplicationMultiplication signHeat transferThread (computing)Real numberProcess (computing)Cartesian coordinate systemVirtual machineConcurrency (computer science)Semiconductor memoryInstance (computer science)HypermediaComputer animation
23:04
Instance (computer science)Core dumpMultiplicationConcurrency (computer science)Thread (computing)Cartesian coordinate systemSet (mathematics)Concurrency (computer science)Human migrationInstance (computer science)BitProcess (computing)Scaling (geometry)Different (Kate Ryan album)Computer animation
23:55
Concurrency (computer science)Thread (computing)Data structureCore dumpCache (computing)Operations researchParallel portLibrary (computing)Thread (computing)Data structureOperator (mathematics)Concurrency (computer science)Different (Kate Ryan album)Multiplication signSystem callWritingReading (process)ResultantMachine codeCache (computing)Core dumpComputer animation
25:06
Thread (computing)Hash functionConcurrency (computer science)GenderAlgebraic closureThread (computing)Level (video gaming)Concurrent engineeringJava appletHash functionCache (computing)Concurrency (computer science)ImplementationMultiplicationLimit (category theory)Social classProcess (computing)MathematicsCovering spaceSet (mathematics)Operator (mathematics)QuicksortPhysical systemData structureAtomic numberView (database)Sign (mathematics)Different (Kate Ryan album)Object (grammar)Random matrixResultantComputer animation
26:24
Atomic numberBefehlsprozessorElectric currentWritingHydraulic jumpAtomic numberThread (computing)Group action1 (number)Object (grammar)NumberRight angleMathematicsState of matterPattern languageLine (geometry)Concurrency (computer science)Block (periodic table)Library (computing)Cartesian coordinate systemCASE <Informatik>Computer animation
27:39
Concurrency (computer science)Software testingEinbettung <Mathematik>Java appletData structureLine (geometry)Right angleCartesian coordinate systemSoftware testingConcurrency (computer science)Library (computing)QuicksortPattern languageThread (computing)Revision controlControl flowMachine codeExistential quantificationComputer animation
28:17
Einbettung <Mathematik>Extension (kinesiology)MereologyMachine codeExistential quantificationEinbettung <Mathematik>Sheaf (mathematics)Computer animation
28:56
Extension (kinesiology)Field extensionInterface (computing)Run time (program lifecycle phase)MetadataWritingExtension (kinesiology)BitJava appletDeclarative programmingSocial classFormal languageField extensionRun time (program lifecycle phase)Process (computing)Multiplication signCASE <Informatik>Computer programComputer animation
29:59
Extension (kinesiology)Source codeJava appletModule (mathematics)Field extensionEinbettung <Mathematik>Traffic reportingMereologyReliefGroup actionProcess (computing)Multiplication signMetadataLibrary (computing)1 (number)Computer animation
31:06
Student's t-testGoogolDreizehnParameter (computer programming)Projective planeMachine codeSelf-organizationService (economics)1 (number)CodeComputer animation
31:44
System on a chipParsingMathematical optimizationCodeExistenceMathematical analysisFitness functionQuicksortDiagramMultiplication signCompilerProjective planeComputer animation
32:17
CompilerMathematical optimizationPoint (geometry)Control flowReading (process)Computer filePoint (geometry)Control flowMiniDiscLie groupProjective planeComputer animation
32:59
Reflection (mathematics)Logical constantBinary fileFile formatBinary fileDiagramMereologyReading (process)Machine codeQuantum stateBasis <Mathematik>Operator (mathematics)Computer animation
33:40
Bit rateInstallation artParsingWhiteboardRule of inferenceMachine codeOperator (mathematics)Cartesian coordinate systemComputer animation
34:19
Complete metric spaceCodeLine (geometry)Complete metric spaceText editorMachine codeBitLibrary (computing)Axiom of choiceComputer animation
34:53
Computer fileAsynchronous Transfer ModePermianIntegerTypinferenzParsingTypinferenzForm (programming)CASE <Informatik>Type theoryAxiom of choiceOpen sourcePoint (geometry)Projective planeLibrary (computing)Functional (mathematics)ParsingComputer animation
36:00
Network topologyQuicksortNetwork topologyFigurate numberOrder (biology)Semiconductor memoryMathematical singularityDifferent (Kate Ryan album)Function (mathematics)Computer fileDifferenz <Mathematik>Computer animation
36:37
Curve fittingParsingOrder (biology)PlastikkarteInstallation artFunction (mathematics)Computer fileVisualization (computer graphics)Computer animation
37:17
Run time (program lifecycle phase)Source codeAbstract syntax treeEvent horizonCartesian coordinate systemLevel (video gaming)Figurate numberPoint (geometry)MathematicsGraphical user interfaceCompilerStreaming mediaSound effectSoftware development kitGoodness of fitMaxima and minimaComputer animation
38:08
Source codeAbstract syntax treeInformationParameter (computer programming)View (database)CompilerCommon Intermediate LanguagePoint (geometry)Machine codeFunction (mathematics)BitCodeProjective planeView (database)InformationDifferenz <Mathematik>PlastikkarteCompilerMathematicsFile formatGoogol
38:52
Hill differential equationResource allocationProjective planeGame controllerDigital photographyWindowPoint (geometry)Control flowCodeComplete metric spaceComputer configurationMachine codeProcess (computing)Functional (mathematics)Computer animation
39:29
Software testingComputer configurationLibrary (computing)Software testingMachine codeProcess (computing)Library (computing)Equivalence relationImplementationFunctional (mathematics)Computing platformComputer animation
40:06
Graphical user interfaceIntegrated development environmentComputing platformBuildingComputing platformIntegrated development environmentPortable communications deviceProjective planeMultiplication signStiff equationDecision theoryCartesian coordinate systemComplex (psychology)Graphical user interfaceBuildingComputing platformSinc functionBitFront and back endsDifferent (Kate Ryan album)Computer animation
41:02
Game theoryBit rateOnline chatGame theoryCopyright infringementVideoconferencingCartesian coordinate systemSpacetimeMachine codeComputer animation
41:46
Game theoryOnline chatAndroid (robot)Multiplication signSelf-organizationFood energyRow (database)Point (geometry)Student's t-testTrailBusiness modelPiLibrary (computing)Run time (program lifecycle phase)RoboticsEncryptionGoodness of fitComputing platformSolid geometryImplementationCartesian coordinate systemMachine codeDifferent (Kate Ryan album)Revision controlCryptographyMatrix (mathematics)CodeComputer animation
43:03
Software testingSoftwareLibrary (computing)Online helpComputer animation
Transcript: English(auto-generated)
00:17
So, we're going to get right into it, talk a little bit about the future of JRuby, we've
00:20
got a little short intro of what it is, but like Tom said, we've got a lot of slides, so we're going to get right into it. So first of all, basically what is JRuby? How many people here have used JRuby for something? Awesome. How many people have something in production right now with JRuby? Alright, so like three quarters and about a half of the room, that's cool. We expected
00:41
that folks coming to this would probably be more on the JRuby side of things. So JRuby, of course, is Ruby on the JVM, and this means a lot of things to a lot of people. A lot of them aren't good things, unfortunately. You get stuff like this, and you know, people, it's all about applets, and the JVM sucks, and people actually go to our code base
01:02
and look for stuff like that. But I mean, the bottom line, the bottom line we always try to get across is really that JRuby is just Ruby. It's a Ruby implementation, it happens to be written partially in Java, happens to run in the JVM, but it's just a Ruby implementation.
01:22
So basics about JRuby before we get into talking about futures, where we're going with it. Right now it's compatible with Ruby 1.8.7 and 1.9.3. This is going to change in the future as we'll talk about. Mostly written in Java, more and more code being written in Ruby, but even the Java code we have is pretty clean. We've got us pretty standard coding
01:42
conventions that we like our committers and contributors to follow. And the coolest part about JRuby, and the reason that most people come to JRuby, is because the entire world of the JVM is available to you. The GCs that we've got available, all the different platforms, the JIT, runtime, and then of course all of the libraries and
02:00
languages that are on the JVM. So it's a Ruby on top of this platform that brings a lot more than just Ruby to the table. Okay, I'm going to talk a little bit about JRuby, how we version and branch, and how we've evolved our development a little bit. When we do a significant release of JRuby,
02:20
we do all of our development on master. Once we hit that 1.6.0, as you know, any project that hits 1.6.0 isn't quite ready to be used yet. So we usually do one or more point release until we feel confident, and then we create a maintenance branch. In the case of 1.6, we did it after 1.6.1. JRuby 1.6 was going to be the great 1.9 release
02:45
for JRuby, and it wasn't. Most of the 1.9 stuff was there, except for encoding, which turned out to be kind of important. A tremendous amount of work. And so time
03:01
march is on. A year later, we put out a preview release on 1.7. We're plugging away on master, working on the next great thing. Another five months, 1.7.0 comes out. So for a year and a half, we're on this dual branch development mode. And what ended up happening is we had so much fun on master that not a lot of stuff made it to 1.6.
03:22
And the branches kept getting further apart, and we did merge stuff when people asked for it, but this was not something that we wanted to repeat. Right. We really like to keep our releases short and closer together, and keep fixes going to the right places to the releases people are using. So when we started working on 1.7, you'll see that we didn't actually create a maintenance
03:45
branch until after 1.7.5. This was us... Right. Keep it real. Yeah. I mean, it's discipline and pain. I was trying to think of the right word to represent the word pain. Rather than going off on a completely new version of JRuby, we forced ourselves to do
04:04
a lot of incremental releases of 1.7 and keep improving it. And we knew that we were going to be working on a major release. So we wanted to make sure that things were really solid by the time we started doing that. In fact, we almost did this at 1.7.3, then realized that we were still missing encoding work on Zlib.
04:21
Encoding is really hard. So the other things that we're going to do to try to make this dual branch development work better is we're going to make sure that we put out a release at least every three weeks. This is to keep us honest. If we go and put out a release in three weeks and it only has one fix in it, then we're not really doing our jobs.
04:41
So this will keep us honest. And the other big change is that anything that involves compatibility, we're going to apply to 1.7 first. And we're constantly merging back to master. Things will be golden. I think we've finally found our sweet spot here. So let's talk about the next major release. One big change, Charlie will show some stats
05:03
in a little bit, but we're only going to support Ruby 2.1. It's coming out sometime next year. It should line up good with MRI. This is going to be awesome. Supporting multiple modes of Ruby at the same time is really painful. We're probably going to be Java 7 and higher. If there's any people that use Java 6 and you're not going to be
05:23
able to migrate by next year, just talk to us. We want to hear who those people are and what your stories are. We want to be modular, both at a packaging level, because platforms like Android, they want to have as small a jar as possible, and also at the source level because things like Google App Engine,
05:41
they don't support sockets, so they shouldn't have to compile against that. Look at this picture, and now look at this next slide. We're going to be breaking lots of APIs. This is the first time that we've actually decided to break a lot of APIs. It's been 10 years or maybe more than 10 years, so we're going to just clean
06:05
up all the crap that we've hated for 10 years, and we're going to have a lot of fun doing it. This mostly affects JRuby Java-based extensions. Obviously, the Ruby compatibility won't hurt at all, but libraries that are written in Java for JRuby may have to make some changes.
06:21
And we have a plan for reducing the pain with regards to embedding, and I'll talk about that a little bit later. And we also have a brand new runtime, which we'll talk about later. I haven't said what the major version number is yet. The natural one would have been 1.8, but JRuby 1.8, which supports Ruby 2.1,
06:40
would have been kind of weird. 1.9, 2.0, same thing. 2.1, that one actually does kind of make sense because we will support 2.1, but then we'd release a 2.2 before MRI did, and then that would be weird. So we should have did this for our version number. We should have went from 1.7 to 8, like Java, but we're weird like that.
07:05
Well, we'll see. We could have picked x and went to 10, like Apple. We kept joking. Ah, we'll just call it 9,000. Okay, and if you couldn't hear that,
07:40
he said it's over 9,000. But our next version is actually JRuby 9,000. And for those people who don't like it, it's just a number. Get over it. And now the work on JRuby 9,000 has actually already started. It's been going faster than
08:05
we expected. This is just some simple stats comparing the JRuby 1.7 line with master, and we're stripping out a ton of code by removing 1.8 support, removing not having two or three copies of standard library, getting the whole of JRuby much smaller. Part of the best
08:23
one here is the complete jar, which is JRuby plus the entire standard library all in one file is already down by about four meg. So we're getting better and better at shrinking down the runtime. I'll talk a little bit about what we're doing to improve the ecosystem going forward. Probably the most difficult part of developing JRuby, and where we've definitely spent the most
08:44
amount of time, is simply on compatibility. We're constantly chasing a moving target, MRI, which has, at various times, had very fast development progress, added large features. And so we've always kind of been trying to catch up. What we're hoping is that with JRuby 9,000,
09:01
we'll be able to match directly up with the 2.1 compatibility, hopefully right around when they do 2.1 release of MRI, we'll have all the features implemented. And then we'll be at our leisure to release or continue working on performance runtime stuff. But hopefully now being able to stay in lock step with MRI and the features that they add. So things that we
09:21
know are still missing. From 1.9, spawn plus all of the different file opening options and redirects and other things, there's a lot of those pieces missing. Largely missing because the JVM zone process management APIs don't support most of them. It's very difficult to do them. Probably have to do a native call out to do these and have full support for them.
09:42
We do have full transcoding support now, and it does work well. We fixed a ton of issues and did a complete rewrite of IO transcoding and coding stuff for 1.7.5. That seems to be doing well. We haven't gotten any real major issues with it. But we're using all the JVM's character-based UTF-16 transcoders. So everything has to go to UTF-16 and then back out to the
10:04
target encoding. That's overhead we'd like to eliminate by porting over the same byte array based transcoding support that MRI has. And that's probably going to come up soon. 2.1 stuff that we know we're missing. Pre-penned, we don't have in there yet. Shouldn't be too difficult. Refinements are going to be officially a feature in 2.1. I worked pretty closely with
10:24
a lot of the MRI folks to try and strip down the feature a little bit, make it not as invasive, not as damaging to performance. And I think we're confident now that we can implement it in JRuby without a major impact. But it's not there yet. We'll have that hopefully by the time MRI 2.1 comes out. And then there's enumerator enhancements that are not quite there yet.
10:43
Size is there. Lazy stuff. Size isn't there. Lazy is. Little bits and pieces from 2.1 that we still need to implement. We're always trying to work on improving the platform in general. Not just for JRuby either. For example, lots of gems for thread safety I'll talk about later. Gems like FFI for calling out to native libraries. Database access, image stuff,
11:06
all this thing, all these things to fill in the blanks for JRuby users. We're constantly working with gem authors to improve performance of their libraries on JRuby, improve performance in general in a lot of cases. Fix threading problems. More and more Ruby gem authors and
11:22
library authors have started to pay attention to threading, testing stuff on JRuby, testing incurrence situations. So we're looking pretty good in that area too. Probably the biggest thing is trying to get more Rubyists testing their stuff on JRuby. Travis is a nice easy way to do it. Otherwise, an RVM setup, getting something local that you can test
11:41
on to help improve the whole platform. We're also gonna continue trying to improve how closely we work with MRI. I've been active on a lot of issues. All of the JRuby team members have been active on issues in the Ruby bug tracker, especially feature-related futures for Ruby that are gonna affect JRuby. Trying to do more on that, especially since
12:03
JRuby's kind of leading the way on concurrency and parallel execution of Ruby code, trying to push that forward and, and take the lead on figuring out how that's supposed to look. I'm actually a committer on MRI and I've fixed a few things. Hopefully doing more of that in the future, trying to clean up standard library, get some threading utilities in there, get some cleanup done. And, and just in general trying to help
12:23
improve the process of evolving Ruby based on how we do JRuby development. So let's talk a little bit about performance that we're gonna work on in the future. So there's a lot that we can do to continue making JRuby, JRuby faster, make Ruby in general faster. The challenges are we've got lots and lots of dynamic calls, very
12:42
dynamic object structures, lots of indirection around. The structure of the objects isn't even fixed at, at startup time. It's defined as instance variables appear. So there's more and more we need to do. The first step of what we do as far as performance is basically just compiling things down to bytecode. The JVM likes bytecode, obviously, and that's
13:02
what it optimizes. So that's the simple first step. What we can do more of here is generating real classes for the Ruby classes that you create. So the JVM sees a normal Java class object, generating instance variable tables that are directly in the object rather than as a tag-along data structure, shrinking everything down, reducing the amount of indirection
13:23
that we have. We've also been hitting invoke dynamic pretty hard. Invoke dynamic is a feature added to Java 7 that basically makes it possible for dynamic languages to plug directly into the JVM and optimize like any statically typed language. It has a bytecode, of course, that represents a dynamic call, and then a series of handles
13:46
and manipulators and argument modifiers to basically describe how to do the dynamic call in a way the JVM can optimize straight through. Now, does this actually work? Does it actually optimize well? Well, this is the, one of the benchmarks I've been showing.
14:00
It's the red-black tree C extension and the Java extension compared to the pure Ruby version. So if we look at Ruby 1.9 and 2.0 with the pure Ruby version, Ruby 2 does a ton of stuff to improve performance. Some of these are inspired by what we've done in JRuby, reducing call overhead and so on, but there's definitely a good improvement
14:21
in 2.0 and 2.1 as far as straight line performance of Ruby code. Maglev and MacRuby, I don't know if anybody's using those lately, they do better. They have actual JIT optimizations that they do, and then are able to be about twice as fast as Ruby 2.0 just by doing some fairly simple JITing. Rubinius has more of an optimizing JIT, and so it's running Ruby code, it actually starts
14:43
to get comparable to the C Ruby versions running with the C extension. The overhead of the Ruby code that wraps the C extension and the call outs to the C extension start to become more overhead for, for MRI here. And now these are the cool ones actually. So this is JRuby on invoke dynamic on Java 7 or 8 with the pure Ruby version in the
15:05
gray here, and it's actually, you know, not quite twice as fast as Ruby 2.0 with the C extension. So we're actually able to run the Ruby version of the Red Black Tree extension, or Red Black Tree library almost as fast, or faster in some cases, as
15:20
the C extension. And then of course JRuby and the Java extension, since it all just looks like Java regardless of whether you're calling into a Java library or calling from Ruby code, the JVM is able to do a significant optimization on that. Now, this is great, and invoke dynamic definitely works as far as the performance you can get out of it, but there's a caveat here. So invoke dynamic when it first came out in
15:42
Java 7 was very slow, it got fast in the first, the second update to Java 7, but that was also broken. There were some severe issues that when you deploy it in production it wouldn't run properly. 7 update 40 rewrote it, and it is now 100% compatible, 100% safe, no bugs with it, but it's very slow to warm up, and it uses significantly
16:05
more memory than the original implementation did. So it's probably going to settle more on Java 8, we have had few users using Java 8 with invoke dynamic not reporting any of the issues that we had during the Java 7 timeframe. So if you're interested in getting the best performance out of it, the Java 8 preview builds would be a good
16:22
way to test it out. Now because of all these issues we've continued to look at other options. One of them that came up recently is a couple of non-JVM JIT projects out of Oracle. There's one called Graal, which is basically an API directly to the JIT in the JVM, and Truffle, which allows you to take languages AST and basically
16:45
convert it directly into Graal calls and optimize it down. Now the early numbers on this have looked good. Oracle did spend about six months doing a proof of concept Ruby implementation on top of Truffle. That's about five or six times faster than JRuby, but the problem here is that they've only got about half of, in this case, Ruby spec
17:05
passing, and there's a lot more that needs to be done. There's probably two or three years worth of work to get that going. What we're hoping is that maybe we'll have some time to explore building a Truffle or Graal-based backend in JRuby itself. And once you add some of the extra vagaries of what Ruby does, that performance is
17:22
probably going to drop. Yeah, exactly. There's a lot of other stuff that they have to put in there, and these libraries are a big part of the performance, too. And I'll hand it over here to talk a little bit more about the new IR-based compiler that we're also working on. Yeah, so IR stands for internal representation, which is probably not the most inventive
17:43
name that we could have come up with, but it's our new runtime. Subramana Sastry created the bulk of IR up to this point. He's a guy who's got a PhD in writing a Java-optimizing compiler, and he basically created an architecture
18:04
that's very similar to a compiler architecture if you read, like, the Dragon book or took a course at university. And we really wanted to create a new runtime because we were fed up with trying to do these optimizations directly from the AST.
18:21
We also wanted something that we weren't going to want to rewrite in five years from now. So we wanted it to be easy to go and plug in new optimizations and have a lot of growth. So here's what IR sort of looks like at the top for JRuby 1.7 and below. We'll lex and parse Ruby code and generate an abstract syntax tree, and then we'll either
18:45
interpret that until it gets warm, and then we'll translate it to Java bytecode as part of a JIT, but in the new IR landscape for 9k, we'll perform some semantic analysis and translate that syntax tree into a set of instructions
19:02
and operands that represent Ruby semantics instead of just syntax. We'll create some supplementary data structures like a control flow graph. After that, we can run a series of optimizations on that, create some more data structures, change some of these existing ones, and then hopefully we'll
19:22
be able to maintain a very thin layer for an interpreter, a pretty simple bytecode generation layer, and we'll be able to expand that out later on to things like Dalvik, ideally trying to do as many optimizations as possible before we even get to the point of generating bytecode for it. So here's our first look at what the instructions are.
19:43
I'll just go down a few of these. At the very top, we make sure that there's two required arguments with check arity. The next three instructions, we assign the parameters, AB, but then we also assign the closure in case someone actually supplied a block to it. Down at line six, you can see C equals one looks like the left side,
20:04
and lines eight and nine represent D equals A plus C. This one doesn't quite read as nice, but it's still pretty simple. We can do all the optimizations that you would expect if you took a
20:21
compilers course. If we find code that we can remove that won't affect how the program runs, we can just eliminate it. If we see a constant value that we know doesn't change, we can just propagate that to where it's used and get rid of the dereferencing from the variable.
20:40
We can inline methods and blocks, though we're not actually using that a lot yet. We do have some early inlining support, though, so it is possible we have managed to make it work. It totally works. It's just figuring out when to do it is a much harder problem than we realized. Here, if we run a couple passes, you can see that we got rid of about half
21:01
the lines of code. You can see we didn't use closure, so we just eliminated that, same with the variable B. On line six, C equals one, we know that C never changes, so we propagate the value one down to the plus call. So now we're doing A plus one instead of A plus C.
21:21
And in general, we're reducing overhead. We have things like block.isGiven littered through our code base. This is a check that's really fast, but it's not free. If you compare that to the dead code elimination aspect of receiving this
21:42
block as an instruction, if we can eliminate it, then we're doing absolutely no work. And no works better than some work. And then as we're able to do some more inlining, a lot of these same optimizations will propagate through multiple methods. Like if it turned out that A plus one, A was also a fixnum, well, maybe we inline it and it actually just turns into two at that point.
22:02
So there's a lot of stuff that we can do to optimize through code once we get the inlining working. And you can just keep reapplying some of the same optimizations after that inlining, it just keeps boiling down. That's the black magic of compiler optimization. When do you stop? All right. So concurrency-wise, most folks know that this is the situation in general.
22:22
Ruby 1.8 was green threaded. Ruby 1.9 plus all have actual native threads, but don't allow parallel execution because of the global lock. Whereas on JRuby, because it's on the JVM, the JVMs had real parallel threads for a long time, we do actually have real threads. You can actually saturate an entire machine with just one JRuby process.
22:42
And where this really comes into play is the cost of deploying wide applications for a lot of users. You look at a 10-way concurrent application in MRI, each process is maybe 100, 200 megabytes. If it's 200 megabytes, that's two gigabytes of memory that you need to allocate. And that's not a trivial instance.
23:01
It's not a huge one. Then we need to scale this thing up. And what if we need to handle 100 concurrent users? Well, then we need to have 100-way concurrency in MRI, which means 100 processes. Now we're getting into 20 gig. This is getting into the very high, very expensive end of, for example, EC2 instances. We recently had someone make a migration to JRuby and saved
23:21
something like $15,000 a month by moving from a whole set of extra larges down to like five mediums. And so there are real tangible benefits to making a move to JRuby and getting threading working well for your application. Looking at how it is in JRuby, one instance, it's going to be a little bit larger as a base cost.
23:42
But you can handle 10 concurrent. You can handle 100 concurrent. You can handle whatever the machine's capable of handling pretty much with one process. Maybe you have one for fallback. But it's a tremendous difference as far as scaling. But there's challenges here too. And this is where a lot of the future work needs to come in. The Ruby world and the Ruby libraries out there are still
24:01
kind of growing into concurrency, growing into parallelism. It hasn't been a big emphasis on threading or concurrent execution in the Ruby world. And so there's more that we need to do. We need tools to make it easier. We need to help make these libraries thread safe. These are some of the key unsafe operations that you're going to see in libraries that aren't thread safe.
24:21
A concurrent read and write on data structures like array, hash, those are not guaranteed to be thread safe. So if you're not doing new texting around those, they can be a problem. A lot of people don't realize that calls like this are not done atomically in any implementation. There's a possibility of a thread jumping in there
24:40
and doing the same increment at the same time. You get different results out of it. And this one, if my cache really, really needs to be allocated only once, this is not a safe way to do it. Because it's very possible that you may allocate two of them if two threads get to that code at the same time. Thread pooling's tough. We need better libraries to do that. Ideally some things that start to get into Ruby core.
25:02
And then just coordinating between threads. And there's better ways of communicating and synchronizing threads together. So a few gems that we like. Some of these we maintain. Some are from friends of ours. The thread safe gem provides concurrency safe hash and array. It also provides, I'm not showing here a cache class,
25:20
which is very, it's hash like. But it uses some of the techniques that the Java concurrency engineers use for concurrent hash map to do fast multi-threaded hash map implementation. But otherwise it's pretty simple. So you construct it, you use it like a normal hash all. And it works pretty much the same way. Hamster is a set of persistent collections for Ruby.
25:43
Now the difference with persistent collections is that you never mutate it in place. Every mutation operation gives you a new reference. Which is that old collection with this change applied to it. So the object you have in hand is always basically read only. And you know that no other mutations happening in a system will impact your reads of it.
26:02
So it's 100% safe as far as concurrency goes. And the nice thing about it is to avoid any sort of locking or magic tricks under the cover. You're just getting a new view of this data structure that everyone else still has their old view of. I won't walk through the whole example here. But it's fairly simple to use. Every mutation you just assign the result
26:22
and then you've got your new collection as a result of it. So for those atomic updates, or equals, plus equals, and so on. There's the atomic gem. Atomic gem basically gives you a wrapped value that you can do atomic updates to. Incremented atomically. Perform some Ruby action atomically. And it will only happen if nobody else jumps in.
26:43
So you'll get the atomic write. Other threads will have to retry again. But it guarantees that no one's gonna step on each other. This is a simple example. We create an atomic object at the top with just a fixed num zero. We can get the value out. We can swap it for another value. And then the more interesting one's doing compare and swap.
27:02
If the existing value is two, put three in there. And then the second line, since we know it's not two anymore, that's not gonna happen. This is how we keep threads from stepping on each other's updates. You can try to make an update only if it's the same state you expect. Down here doing more advanced atomic updates, update with a block,
27:22
will only make that change if no other thread jumps in there at the same time. And if another thread jumps in, it'll try and make the change. In this case, it'll redo that block. And down here, it'll raise an error. You can decide whether you wanna try and continue doing this update.
27:40
So the bottom line for these libraries is that concurrency really can work in Ruby. And there's a lot of people doing highly concurrent applications on JRuby right now. But we need the right kind of tools and the right patterns to do it. Immutability really helps. Having some of these sort of data structures helps. And testing on JRuby is really the only way to know if your library is gonna be thread-safe.
28:02
We've got the most extensive threading support and we've had it for the longest, so it's just best if you test on JRuby to make sure. Okay, I mentioned earlier that I wanted to talk about improving embedding, especially since we're moving to a new major version that's gonna break APIs. First thing is public is similar to public in Ruby
28:22
in that once something's marked public, anything can call it. We have a huge code base and we need to mark a bunch of things public. Unfortunately, because it's public, then any native extension can call it as well. And I don't blame people for doing it. They're calling these methods because they have to.
28:40
And they probably represent gaps in our embedding API. But we need to actually signal our intent that we think that these are blessed APIs you can use versus we don't want you to use these. So we're gonna also provide a tool and let's look at the solution. Or part of the solution. This is actually a problem that MRI has faced with the C extension API.
29:02
Without hiding some of it, everything becomes the public API and that's a big reason why C extensions are hard or impossible to support other implementations. C doesn't have visibility at all, so we get a little bit more protection, but not a lot. So I'm not gonna teach people how to go and write annotations in Java. This is RubyConf, but this is really great.
29:23
I'm just gonna talk about annotations a little bit. This is metadata that you can attach to first class concepts in the language. So in this case, we're creating an annotation called extension that we can attach to methods. So we'll just put add extension in front of our method declaration.
29:43
And then we specify that it has a runtime binding, which means in your live running Java program, you could actually ask that method at runtime, are you an extension method? So this metadata concept is really cool. In usage, in our source,
30:02
we'll just mark the methods that we have as extensions. And then in our native extensions, we can use those and then run a tool. We haven't actually wrote the tool, but it'll be integrated into JRuby lint. It'll examine your jar and it'll give you a report of things
30:21
that you are using that aren't blessed. Right, this is part of the transition. We know we're gonna break some of those external APIs, but we know the ones we're going to bless as official and can give reports to any library that's out there using the bad APIs, what they're using now and what they need to change to. We kind of get a double benefit as well
30:40
because we can actually write a documentation generator and we can actually generate an embedding document from these annotations. And the reason why I spent a little extra time on this was because wouldn't it be really great if in Ruby 3 we actually added a metadata facility so that we could go and attach stuff to methods. There's just so many uses for this. It'd be really nice to consider adding something
31:03
similar to Java annotations. We're gonna go and cover some projects associated with Google Summer of Code. JRuby actually had its own organization for this and well, examples are probably the best way to show. We have some Google Summer of Code people here.
31:22
There's one in front, okay. I think maybe the other one's in my, there's one other that's here, I think. I haven't seen them around yet, but we had about, we had 10 people this year. How many did we have last year? Oh, it was more. It was more, I think we had 13. It was like 14 or something? We had 13 students last year, 10 students this year. So we're really trying to help get more students
31:40
into JRuby and into Ruby in general. The first one is actually from last year, but it kind of fits into the talk about IR. We realized we had a problem with IR and we sort of still have that problem. This diagram totally shows it.
32:02
We're doing more work. If you think about JRuby, the one thing that we're known for that we don't want to be known for is our startup time. So our startup time's getting a little more overhead today. Yeah, let's add more overhead. But we realized this in, well, before 2012
32:20
and we had Alexa make work on a persistence project, basically similar to just a compiler. You just save your persistent data and then you read it in instead of having to recompile. So if the file's up to date and it's been saved, you just read that and save having to compile.
32:41
And ultimately, we have a break even point. We have to be able to read that off a disk faster than we can actually compile. And this is kind of a lie. We actually have to be faster than 1.7 today or people are gonna go, why did you slow JRuby down even more for startup? Unfortunately, for this project,
33:01
it ended up taking longer to read the data and then it took to actually compile it. But it basically boiled down to we were saving way too much data. Size really does matter for read speed. Also, we realized that a majority of the stuff that we were actually reading in, we never actually used.
33:21
So we wanna be more lazy. I'm not gonna talk about interning. It was, but we'll cut down. So we're gonna use a binary format. And the most important part is that we're going to do incrementally loading to be lazy and this diagram will show you why.
33:41
If you look at all the basic operations you would do on a day-to-day basis, you'll notice this really strange ratio. It's an 80-20 ratio. 80% of the code that you actually load when you start up each of these activities is never actually called. Now, maybe for a longer running application, it does get called, but it seems like for startup and common activities,
34:04
the 80-20 rule applies, which is really, really weird. Yeah, it's weird that that ratio applied almost across the board. So if we define the methods but we don't actually parse any of the bodies, then we're obviously gonna be doing a lot less parsing.
34:22
RSense was updated. Eric West is here. Let's stand up quick. You have to embarrass him a little bit. If you haven't seen RSense, it's a library that you can go and install
34:42
and put into your editors like VI or Emacs and it can do simple things like code completion, but it actually makes smart choices because it actually has a full type inference engine. In this case, this is a pretty simple form
35:01
of type inference, but it can figure out a surprising amount of stuff. So it's something worth looking into. But before I talk about how to do that, let's just grab the project. The person who originally wrote it wrote it against JRuby and he wrote it against JRuby 1.3.
35:23
At some point after JRuby 1.3, we ripped a bunch of stuff that he needed out of it and put it into its own library and then like all great open source projects went into decay. But one of the downsides is you could still use it today but it would only support 1.8 syntax, which is a problem.
35:42
And so Eric wanted to fix that. A second goal we had was that if there was any really interesting functionality that was in RSense, that would be useful for the JRuby parser project itself, that he would go and move that in or implement it differently, but move it in.
36:03
So he did that and it's good to go, except RSense hasn't been released. So we have to talk to Matsuyama-san and figure out how to get this released as a new gem. Eric added this really cool tree differencing support so you can compare two different sub-trees
36:22
and do all sorts of things with it. And one thing that he did with it concretely is he made a gem called smart diff. So if you go and take a diff between two files, you'll get an HTML file that looks like this. You'll see the blue and gray highlighting back and forth.
36:44
Smart diff's actually able to tell that I just switched the order of these two files. And then you'll see that typical green and red output for things that are added or deleted. It's pretty cool. So you can use this, just gem install.
37:01
This is just built on top of RSense. There's obviously a lot more stuff we can do with this. Oh, this is actually just built on JRuby parser. Oh, it's just built on a parser. JRuby Visualizer is by Maximin Konczak. He's not here today. We need to have better tools
37:20
to go and analyze stuff at the IR level. We have a lot of compiler passes running. And in particular, eventually we want to get this tool to the point where you can go and run your application and it'll generate an event stream. You can save that event stream, give it to us, and we can look at all the changes that are happening
37:41
in the IR and figure out what went wrong. Right, see why it's not optimizing what it should be. It's a GUI-based application. It's written on top of the JRubyFX gem, which is something that myself, Eric, and Max work along with mostly byte IT 101. I can't pronounce his last name,
38:01
so I'm just gonna use this handle. But that's an awesome GUI toolkit on JRubyFX. Okay, so here's just a couple of screenshots. If you go and click on the AST on the left, it'll just scroll to wherever on the right and show you what code that is. So there's a little bit of traceability introduced.
38:22
At any point, I don't expect you to read that, but it's more IR output. Actually, that's bigger than I thought. It'll actually ask for the compiler passes executed, and you can step through those and then pop up the IR view to see what's changed.
38:41
We actually want this to be a more smart diff format to actually get better information how it's changed, but it's a Google Summer of Code project. Guy can only do so much. And lastly, you can go and look through at the control flow graph, and we wanna go and add more windows for more stuffs.
39:02
Okay. Another project we had this summer, Chamila worked on DTrace support for us. So Ruby 2.1 added DTrace probes. I think that was Aaron Patterson added that. We wanted to have the same thing, and Chamila came along and decided that that was the project he'd like to do for Google Summer of Code.
39:21
It turns out OpenJDK does have DTrace support in it, so we could just build on top of those existing APIs. Now what we have right now, it's about 90% complete, and it passes a lot of MRIs tests for the functionality that we've implemented. But the thing we found out during the process is that unfortunately, the DTrace support in OpenJDK
39:42
only exists on Solaris right now. So we're looking at other options, pulling the DTrace support over to the BSDs like OS 10, where we have DTrace, pulling over the same APIs to Linux equivalents of DTrace, or possibly calling out to an external library. But we do have the code available.
40:01
We're gonna try and get it merged in, at least for the Solaris platforms, and then see what we can do for others. Shoes, Shoes 4 was another project that came along this summer. We've also did some work last summer, too. Tobias worked on this one. So Shoes is basically Y.TheLuckyStiff's GUI environment. It's very clean, very simple to use.
40:22
He wanted to come up with something that would be really trivial and fun to build complex GUI applications with. Shoes 4 actually made the decision last year sometime, I think, to move to a JRuby-only backend. There's a lot of reasons for this. Most of them, portability, not having to build the libraries over and over again, and having a consistent experience across all platforms.
40:43
Building it on top of GTK or Win32 or whatever else never worked great across platforms. Things always felt a little bit different, and it was very difficult to ship applications since everybody needed to install all those extra libraries and build them for that platform. In the other room, in one of the salons,
41:02
there's actually a talk on an application that uses DRB and Shoes 4 to do a space team-like pirate game. And that's Davey, Eric, and Ryan are talking about that in the other room. And since they couldn't be here and we couldn't be there, I thought we'd get a video from them
41:20
to show this application running. And so this is just all, this is written all in Ruby code using Shoes, which is backed by SWT, one of the JVM GUI libraries. Any space team players here? Not too many. The goal basically is you have two or three or four people and it shouts out commands to you
41:41
and you have to do them quickly, or yell it out to your friends so that they'll do the commands. So there you go. So that's fun and it's cool that it's actually being used now. Some more Google's Google Summer Code stuff we don't have time to cover. More work on Rubata, which is JRuby on Android, trying to strip down the runtime, improve performance,
42:02
make it easier to build Android applications entirely in Ruby. Asakawa Ryu did that. Shoes 4, Hackety Hack support, Faraz did that. We mostly let the Shoes guys mentor that, so we didn't track that very much. For the second year in a row, we had two students working on Crypt. Crypt is a new encryption encoding library for Ruby
42:25
intended to hopefully replace OpenSSL at some point. But implemented in Ruby where it can be, native where possible, and supporting all the implementations at the same time. So we've always got a good, solid encryption library.
42:40
And we're very happy that we're able to support that every year in Google Summer Code. We also had a student explore JRuby on embedded devices like Raspberry Pis and stuff like that. He basically came up with a bunch of different matrices of which libraries, which JRuby versions work on which platforms with which embedded JVMs. And we've got all that information available
43:00
in the JRuby organization on GitHub. So, wrapping things up. Emphasizing that JRuby is just Ruby, it just happens to be on the JVM. We're working with the MRI and the community a lot more, more and more in the future. If anybody has gems or libraries you're releasing, please, please turn on JRuby and Travis.
43:20
If it's not passing, let us know and we'll help you figure out why. And if you're not trying JRuby right now, give it a shot. Let us know how it goes for you and let us know what we can improve. So thanks.