-
CHARLES NUTTER: So we're gonna get right into
it.
-
I talk a little bit about the future of JRuby.
-
We've got a little short intro of what it
is.
-
But, like Tom said, we've got a lot of slides
so we're gonna get right into it.
-
So first of all, basically, what is JRuby?
How
-
many people have used JRuby for something?
Awesome. How
-
many people have something in production right
now with
-
JRuby? All right.
-
So like, three-quarters and about a half of
the
-
room. That's cool. We expected that most of
you
-
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, and,
-
you know, people - it's all about applets,
and
-
the JVM sucks, and people, people actually
go to
-
our code base 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. It
happens
-
to run on the JVM. But it's just a
-
Ruby implementation.
-
So basics about JRuby, before we get into
talking
-
about futures, where we're going with it.
It, right
-
now it's compatible with Ruby 1.8.7, and 1.9.3.
This
-
is gonna 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 a pretty standard
-
coding 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 GIT runtime. And then of course
all
-
of the libraries and languages that are on
the
-
JVM.
-
So it's, it's a Ruby on top of this
-
platform that brings a lot more than just
Ruby
-
to the table.
-
TOM ENEBO: OK. I'm gonna 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, 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, like, 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 gonna be the
-
great 1.9 release for JRuby, and it wasn't.
-
Most of the 1.9 stuff was there, except for
-
encoding, which was a-
-
C.N.: Turned out to be kind of important.
-
T.E.: A tremendous amount of work. And so
time
-
marches 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.
-
Oh, 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 in master that not a
-
lot of stuff made it to 1.6, 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.
-
C.N.: Right. We really want to keep our releases
-
short and closer together. And, and keep fixes
going
-
to the right places. To the, to the releases
-
people are using.
-
T.E.: So when we started working on 1.7, you'll
-
see that we didn't actually create a maintenance
branch
-
until after 1.7.5. This was us-
-
C.N.: Right, keep it real.
-
T.E.: Yeah, I mean. It's discipline and pain.
I
-
was trying to think of the right word to
-
represent pain.
-
C.N.: Rather than going off on, on a completely
-
new version of JRuby, we forced ourselves
to do
-
a lot of incremental releases for 1.7, to
keep
-
improving it.
-
T.E.: And we knew that we're gonna be working
-
on a major release. So we wanted to make
-
sure that things are really solid by the time
-
we started doing that.
-
And in fact we almost did this at 1.7.3,
-
then realized that we were still missing encoding
work
-
on zlib. And coding's really hard.
-
So the other things that we're gonna try to
-
do to try to make this dual-branch development
work
-
better, is we're gonna 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 job, so. This'll keep
us
-
honest.
-
And the other big change is that anything
that
-
involves compatibility, we're gonna apply
to 1.7 first. And
-
we're constantly merging back to Master. Things'll
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
in
-
a little bit, but we're only gonna support
Ruby
-
2 point 1. It's coming out sometime next year.
-
It should line up good with MRI.
-
This is gonna be awesome. Supporting multiple
modes of
-
Ruby at the same time is really painful.
-
We're probably gonna be Java 7 and higher.
If
-
there's any people that use Java 6, and you're
-
not gonna be 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 - cause 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, 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 gonna be breaking lots of APIs. This
is
-
the first time that we've actually decided
to break
-
a lot of APIs. It's been ten years, or
-
maybe more than ten years. So we're going
to
-
just clean up all the crap that we've hated
-
for ten years, and we're gonna have a lot
-
of fun doing it.
-
C.N.: This mostly affects, like, 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.
-
T.E.: 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're also gonna
-
have a brand new runtime, which we'll talk
about
-
later.
-
So I haven't said what the major version number
-
is yet. The natural one would have been 1
-
point 8, but JRuby 1 point 8, which supports
-
Ruby 2 point 1, would have been kind of
-
weird. 1 point 9, 2 point 0, same thing.
-
2 point 1? That one actually does kind of
-
make sense, cause we will support 2 point
1,
-
but then we'd release a 2 point 2 before
-
MRI did, and 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. We,
well,
-
we'll see.
-
We could have picked X and went to ten
-
like Apple.
-
We kept joking. Ah, we'll just call it nine
-
thousand.
-
I hope people can hear this.
-
-VIDEO-
-
Character: What does the scouter say about
his power
-
level?
-
OTHER: It's over nine thousand!!!
-
Character: What, nine thousand? There is no
way that
-
can be right!
-
T.E.: OK, and if you couldn't hear that, he
-
said it's over nine thousand.
-
But our next version is actually JRuby 9000.
-
And for those people who don't like it, it's
-
just a number. Get over it.
-
C.N.: Now that - the work on JRuby 9000's
-
actually already started. It's been going
faster than we
-
expected. This is just some, 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. Probably
the
-
best one here is the, 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, we're getting better and better
at shrinking
-
down the runtime.
-
We'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 we're
definitely spent
-
the most 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
-
9000, we'll be able to match directly up with
-
the 2 point 1 compatibility, hopefully right
around when
-
they do 2 point 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 the things that we know are still missing.
-
From 1 point 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 JVMs own process management APIs
don't support
-
most of them. It's very difficult to do them.
-
We'll probably have to do a native call-out
to
-
do these in full, have full support for them.
-
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 JVMs character-based
UTF16 transcoders,
-
so everything has to go to UTF16 and then
-
back out to the 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 gonna come up soon.
-
2 point 1 stuff that we know we're missing.
-
Prepend. We don't have it in there yet. Shouldn't
-
be too difficult. Refinements are going to
be officially
-
a feature in 2.1. I've worked pretty closely
with
-
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, 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 point 1 comes out.
-
And then there's enumerator enhancements that
are not quite
-
there yet. Size is there, lazy stuff - size
-
isn't there, lazy is. Little bits and pieces
from
-
2 point 1 that we, we still need to
-
implement.
-
We're always trying to work on improving the,
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. 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 and performance
in general,
-
in a lot of cases. Fixed threading problems.
More
-
and more Ruby gem authors and library authors
have
-
started to pay attention to threading, testing
stuff on
-
JRuby, testing in concurrent 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
-
set-up, getting something local that you can
test on,
-
to help improve the whole platform.
-
We're also going to continue trying to improve
how
-
closely we work with MRI. I've been active
on
-
a lot of issues. All of JRuby team members
-
have been active on issues in the Ruby bug
-
tracker, especially feature-related futures
for Ruby that are going
-
to affect JRuby.
-
Trying to do more on that. Especially since
JRuby's
-
kind of leaned away 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, try and clean up standard library.
Get
-
some threading utilities in there, get some
cleanup done.
-
And, and just in general trying to help 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 faster, make Ruby in general faster.
-
The challenges are, we've got lots and lots
of
-
dynamic calls, very dynamic object structures,
lots of indirection
-
around. The structure of the objects isn't
even fixed
-
at startup time. It's defined as instance
variables up
-
here. 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
-
byte code. The JVM likes byte code, obviously,
and
-
that's 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 ass a tag-a-long data structure.
Shrinking
-
everything down, reducing the amount of indirection
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 byte code, of course, that represents
-
a dynamic call, and then a series of handles
-
and, 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 this actually
optimize
-
well?
-
Well, this is one of the bench marks I've
-
been showing. It's, the red-black tree C-extension,
and the
-
Java extension, compared to 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 in 2.0 and 2.1 as far as
-
straight-line performance of Ruby code.
-
Maglov and MacRuby, I don't know if anybody's
using
-
those lately. They, they do better. They have
actually
-
git optimizations that they do, and then are
able
-
to be about twice as fast as Ruby 2.0
-
just by doing some fairly simply gitting.
-
Rubinius has more of an optimizing git, and
so
-
it, running Ruby code, it actually starts
to get
-
comparable to the CRuby 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 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 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, a lot faster
in
-
some cases, as the C extension.
-
And then of course JRuby in 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 is a caveat here.
-
So invoke dynamic, when it first came out
in
-
Java 7, was very slow. It got fast in
-
the first, the, the second update to Java
7,
-
but that was also broken. There was some severe
-
issues that, when you deployed in production
it wouldn't
-
run properly.
-
7, update 40, rewrote it, and it is now
-
100% compatible, 100% no bugs with it. But
it's
-
very slow to warm up, and it uses significantly
-
more memory than the original implementation
did.
-
So it's probably going to settle more on Java
-
8. We have had a few users using Java
-
8 with invoke dynamic, not reporting any of
the
-
issues that we had during the Java 7 time
-
frame.
-
So if you're interested in getting the best
performance
-
out of it, the Java 8 preview builds would
-
be a good way to test it out.
-
Now, because of all these issues we continue
to
-
look at other options. One of them that came
-
up recently is a couple non-JVM git projects
out
-
of Oracle, call- there's one called Graal,
which is
-
basically an API directly to the git in the
-
JVM, and Truffle, which allows you to take
languages
-
AST, abstract syntax tree, and, and basically
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 the, in this case, Ruby spec 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 of Graal
based
-
backend in JRuby itself.
-
T.E.: And, and once you add some of the
-
extra vagries of what Ruby does, that performance
is
-
probably going to drop.
-
C.N.: Yeah, exactly. There's a lot of other
stuff
-
that they have to put in there. And, and
-
these libraries are a big part of performance,
too.
-
So.
-
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.
-
T.E.: Yeah, so, IR stands for internal representation,
which
-
is probably not the most inventive name that
we
-
could have come up with. But it's our new
-
runtime. Subramanya Swarovski created the
bulk of IR up
-
to this point. He's the guy who got a
-
PhD in writing a Java optimizing compiler.
-
And he basically created an architecture 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 AST. We also wanted
something that
-
we weren't going to want to rewrite five years
-
from now. So we wanted it to be easy
-
to go and plug in to 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, will
-
lex and parse Ruby code and generate an abstract
-
syntax tree, and then will either interpret
that until
-
it gets warm, and then we'll translate it
to
-
Java byte code as part of a git, but
-
in the new IR landscape for 9k, we'll perform
-
some semantic analysis and translate that
syntax tree into
-
a set of instructions and operands that represent
Ruby
-
semantics, instead of just syntax.
-
We'll create some supplementary data centers,
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 build a maintain a very thin layer for
-
an interpreter. Pretty simple byte code generation
layer, and
-
we'll be able to expand it out later on
-
to things like Dalvik.
-
C.N.: Ideally trying to do as many optimizations
as
-
possible, before we even get to the point
of
-
generating byte code.
-
T.E.: So here's our first look at what the
-
instructions are. 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, a, b, 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, 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 compiler's course. If
we
-
find code that we can remove that won't effect
-
how the program runs, we can just eliminate
it.
-
If we, 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,
-
the dereferencing from the variable.
-
We can inline methods and blocks that we're
not
-
actually using a lot yet.
-
C.N.: We do have some early inlines for it
-
though, so it is possible we have managed
to
-
make it work.
-
T.E.: Oh it, it totally works. It's just figuring
-
out when to do it is, is a much
-
harder problem than we realized.
-
So here, if we run a couple passes, you
-
can see that we got rid of about half
-
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 equals one, we
-
know that it 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.
-
And, in general, we're reducing overhead.
We have things
-
like block that is given, 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 block as
-
an instruction, if we can eliminate it, then
we're
-
doing absolutely no work, and no work's better
than
-
some work.
-
C.N.: 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 turns out
-
that a plus one, a was also a fixnum,
-
while maybe we inline it and just turns in
-
to it at that point.
-
So there's a lot of stuff that we can
-
do to, to optimize through code once we get
-
the inlining working.
-
T.E.: And you can just keep reapplying some
of
-
the same optimizations after that inlining
and just-
-
C.N.: Right.
-
T.E.: -keeps boiling down.
-
C.N.: That's the black magic of compiler optimization.
When
-
do you stop?
-
All right, so concurrency-wise, most folks
know that this
-
is the, the situation in general. 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
-
JVM's 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.
-
And where this really comes into play is the
-
cost of deploying wide applications for a
lot of
-
users. You look at a ten-way concurrent in
MRI,
-
each process is maybe a hundred, two hundred
megabytes.
-
If it's two hundred megabytes, that's two
gigabytes of
-
memory that you need to allocate. And that's
not
-
a, that's not a trivial instance. It's not
a
-
huge on.
-
But then, what if we need to scale this
-
thing up? And what if we need to handle
-
a hundred concurrent users? Well, then we
need to
-
have a hundred-way concurrency in MRI, which
means a
-
hundred processes. Now we're getting into
twenty 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 save something like fifteen thousand dollars
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, and getting threading
working
-
well for your application.
-
Look at how it is in JRuby. One instance,
-
it's going to be a little bit more, a
-
little bit larger as a base cost, but you
-
can handle ten instances, ten concurrent,
you can handle
-
a hundred concurrent. You can handle whatever
the machine's
-
capable of handling, pretty much with one
process. Maybe
-
you have one for fall back, but it's, 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 kind of growing into concurrency,
growing
-
into parallelism. And there 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
-
a lot, we need to help make these libraries
-
thread safe.
-
These are some of the key unsafe operations
that
-
you're gonna see in, in libraries that aren't
thread
-
safe. Concurrent read and write on, on data
structures,
-
like array, hash - those are not guaranteed
to
-
be thread safe. So if you're not doing mutexing
-
around those they can be a problem.
-
A lot of people don't realize that, that calls
-
like this are not done automatically in any
implementation.
-
There's a possibility of a thread jumping
in there
-
and doing the same increment at the same time.
-
You get different results out of it.
-
In 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. And then just coordinating between
threads. Better
-
ways of communicating and synchronizing threads
together.
-
So a few gems that we, we, 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, which is very, it's hash-like,
but it
-
uses some of the techniques that the, the
Java
-
concurrency engineers use for concurrent hash
map to do
-
fast multi-threaded hash map implementation.
-
But otherwise pretty simple. You construct
it, you use
-
it like a normal hash almost. And it works
-
pretty much the same way.
-
Hamster is a set of persistent collections
for Ruby.
-
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 the system will impact your reads
of
-
it.
-
So it's a hundred percent safe as far as
-
concurrency goes, and the nice thing about
it is
-
it avoids any sort of locking or magic tricks
-
under the cover. You just getting a new view
-
of this data structure that everyone still
has their
-
old view of.
-
I won't walk through the whole example here
but,
-
it's, it's fairly simple to use. Every other
mutation,
-
you just assign the result and then you've
got
-
your new collection as a result.
-
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. Increment it atomically,
perform some
-
Ruby action atomically, and will only happen
if nobody
-
else jumps in. So, so you'll get the atomic
-
right. 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, which is just a fixnum
-
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,
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 will
-
only make that change if no other thread jumps
-
in there at the same time.
-
And if the, if you need the, if another
-
thread jumps in, it'll try and make the change.
-
It'll eith- in this case, it'll redo that
block
-
and down here it'll raise an error. You can
-
decide whether you want to try to continue
doing
-
this update.
-
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. We've got the most extensive
-
threading support, and we've had it for the
longest,
-
so it's just best if you test it on
-
JRuby to make sure.
-
T.E.: OK, 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 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 cause they have to.
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 them.
-
So we're gonna also provide a tool, and let's
-
look at the solution - or part of the
-
solution.
-
C.N.: This is actually a problem that MRI
is
-
faced with the C extension API. 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.
-
T.E.: Well, C doesn't have visibility at all,
so
-
we get a little bit more protection, but not,
-
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. 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 and, and
then
-
we specify that it has a runtime binding,
which
-
means in your live-running Java program you
could actually
-
ask that Java method at runtime, are you an
-
extension method?
-
So this metadata concept is, is really cool.
In
-
usage, in our source 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
-
that you are using that aren't blessed.
-
C.N.: 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.
-
T.E.: We kind of get a double benefit as
-
well, 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
-
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.
-
C.N.: We're, we have some Google Summer of
Code
-
people here. There's one in front - OK. I
-
think some of the other ones that might, there's,
-
there's one other that's here, I think. I
haven't
-
seen him around yet but, we had about, we
-
had ten people this year. How many did we
-
have last year?
-
T.E.: It was more.
-
C.N.: It was more, I think it was like-
-
T.E.: It was like fourteen.
-
C.N.: Thirteen? Thirteen students last year.
Ten students this
-
year. So we're really trying to help get more
-
students into JRuby and into Ruby in general.
-
T.E.: The first one is actually from last
year.
-
But it kind of fits into the talk about
-
opt IR. We realized we had a problem with
-
IR, and we sort of still have that problem.
-
This diagram totally shows it. 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.
-
C.N.: It sucks.
-
T.E.: So our startup time's getting-
-
C.N.: Want a little more overhead?
-
T.E.: Yeah. Let's add more overhead.
-
But we realized this, in, well before 2012,
and
-
we had Aliaksei make a, 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.
-
And ultimately, we have a break-even point.
We have
-
to build and read that off a disk faster
-
than we can 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, it ended up
taking longer
-
to read the data in than it took to
-
actually compile it. But it basically boiled
down to,
-
we were saving way too much data. Size really
-
does matter for, for read speed.
-
Also, we realized that a majority of the stuff
-
that we were actually reading in, we never
actually
-
used. So we want to be more lazy. I'm
-
not gonna talk about interning. I was, but
we'll
-
cut down.
-
So we're gonna use a binary format. And the
-
most important part is that we're gonna do
incrementally
-
loading to be lazy, and this diagram will
show
-
you why. 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
eighty-twenty ratio.
-
Eighty percent of the code that you actually
load
-
when you startup, 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, and common activities, the eighty-twenty
rule applies.
-
Which is really, really weird.
-
C.N.: Yeah, it's weird that that ratio applied
almost
-
across the board.
-
T.E.: So if we define the methods but we
-
don't actually parse any of the bodies, then
we're
-
obviously going to be doing a lot less parsing.
-
RSense was updated. Eric West is here. Stand
up
-
quick. I have to embarrass him a little bit.
-
If you haven't seen RSense, it's a library
that
-
you can go and install, and put in to
-
your editors, like VI or eMacs, and it can
-
do simple things like code completion. But
it actually
-
makes smart choices, because it actually is
a full-type
-
inference engine.
-
In this case, this is a pretty simple form
-
of type inference, but it can figure out a
-
surprising amount of stuff. So it, it's something
worth
-
looking into. But before I talk about how
to
-
do that, let's describe the project.
-
The person who originally wrote it, wrote
against JRuby,
-
and he wrote it against JRuby 1 point 3.
-
At some point after JRuby 1 point 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 opensource projects,
it 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. And so Eric wanted
-
to fix that.
-
A second goal we had was that, if there
-
was any really interesting functionality that
was in, our
-
sense that would be useful for the JRuby parser
-
project itself, that he would go in and move
-
that in. Or implement it differently, but
move it
-
in.
-
So he did that. And it's good to go
-
except RSense hasn't been released. So we
have to
-
talk to Matzuyama's son 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 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 grey highlighting back and forth.
-
Smart_diff is actually able to tell that I
just
-
switched the order of these two files. And
then
-
you would see the typical green and red output
-
for things that are added or deleted. It's,
it's,
-
it's pretty cool.
-
So you can, you can use this just gem
-
install.
-
C.N.: It's just built on top of RSense. It
-
was a lot, obviously a lot more stuff we
-
could do with this.
-
T.E.: Oh, this is actually just built on JRuby
-
parser.
-
C.N.: Oh it's just built on the parser.
-
T.E.: Yeah.
-
jruby_visualizer is by Maximilian Konzack.
He's not here today.
-
We need to have better tools 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
in
-
the IR and figure out what went wrong.
-
C.N.: Right. See why it's not optimizing what
it
-
should be.
-
T.E.: It's a GUI based application. It's certainly
written
-
on top of the JRubyFX gem, which is something
-
that, myself, Eric, and Max, worked along
with mostly
-
byte IT 101.
-
I don't, I can't pronounce his last name,
so
-
I'm just gonna use his handle. But it's an
-
awesome GUI toolkit on JRubyFX. Use it.
-
OK. So here's just a couple of screen shots.
-
If you go and click on the AST in
-
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 trace ability introduced.
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. 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. A guy
-
can only do so much.
-
And lastly you can go and look through the
-
control flow graph. And we want to go in
-
and add more windows for more stuff. So.
-
MK.
-
C.N.: Another project we had this summer,
Chamila worked
-
on DTrace Support for us. So Ruby 2 point
-
1 added DTrace probes. I think that was, Erin
-
Patterson added that.
-
We wanted to add the same thing, and Chamila
-
came along and decided that that was the project
-
that he'd like to do for Google Summer of
-
Code. 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, the functionality that we've implemented.
But the
-
thing we found out during the process is that,
-
unfortunately the DTrace support in OpenJDK
only exists on
-
Solaris right now.
-
So, we're looking at other options, pulling
the DTrace
-
support over to the BSDs, like OS ten where
-
we have DTrace. Pulling over the same APIs
where
-
we have Linux equivalents of DTrace. Or possible
calling
-
out to a, an external library.
-
But we do have the code available. We're gonna
-
try to get it merged in at least for
-
the Solaris platforms and see what we can
do
-
for others.
-
Shoes. Shoes4 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
-
why the lucky stiff's GUI environment. It's
very clean,
-
very simple to use. He wanted to come up
-
with something that would be really trivial
and fun
-
to build complex GUI applications with.
-
Shoes4 actually made the decision, last year
some time
-
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. Building it on top of GTK or Win32
-
or whatever else never worked great across
platforms. Things
-
always developed a little bit different and
it was
-
very difficult to ship applications, since
everybody needed to
-
install those extra libraries and build them
for that
-
platform.
-
In the other room, in one of the salons,
-
there's actually a talk on an application
that uses
-
DRb and Shoes4 to do a Space Team-like pirate
-
game. And that's Davy, 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 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. Anybody
-
play - 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, 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 was, that's fun,
-
and it's cool that, that it's actually being
used
-
now.
-
Some more Google Summer of Code stuff we don't
-
have time to cover - more work on Ruboto,
-
which is JRuby on Android, trying to strip
down
-
the runtime, improve performance, make it
easier to build
-
Android applications entirely in Ruby. Asakawa
Ryu did that.
-
Shoes4 HacketyHack support. Faraaz did that.
We don't, we
-
mostly let the Shoes guy mentor that, so we
-
didn't track that very much.
-
For the second year in a row we had
-
two students working on Krypt. Krypt is a
new
-
encryption, encoding library for Ruby, 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.
-
And we're very happy that we're able to support
-
that every year in Google Summer of Code.
-
And we also had a student explore JRuby on
-
embedded devices like raspberry pies and stuff
like that.
-
He basically came up with a bunch of different
-
matrices of which libraries, which JRuby,
which JRuby versions
-
work on which platforms with which embedded
JVMs. And
-
we've got all that information available on,
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. If it's not
-
passing, let us know and we'll help you figure
-
out why.
-
And, you know, 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.