< Return to Video

Ruby Conf 2013 - The Future of JRuby by Charles Nutter and Thomas Enebo

  • 0:16 - 0:18
    CHARLES NUTTER: So we're gonna get right into
    it.
  • 0:18 - 0:20
    I talk a little bit about the future of JRuby.
  • 0:20 - 0:23
    We've got a little short intro of what it
    is.
  • 0:23 - 0:27
    But, like Tom said, we've got a lot of slides
    so we're gonna get right into it.
  • 0:27 - 0:30
    So first of all, basically, what is JRuby?
    How
  • 0:30 - 0:33
    many people have used JRuby for something?
    Awesome. How
  • 0:33 - 0:36
    many people have something in production right
    now with
  • 0:36 - 0:37
    JRuby? All right.
  • 0:37 - 0:40
    So like, three-quarters and about a half of
    the
  • 0:40 - 0:41
    room. That's cool. We expected that most of
    you
  • 0:41 - 0:43
    coming to this would probably be more on the
  • 0:43 - 0:45
    JRuby side of things.
  • 0:45 - 0:48
    So JRuby of course is Ruby on the JVM,
  • 0:48 - 0:49
    and this means a lot of things to a
  • 0:49 - 0:51
    lot of people. A lot of them aren't good
  • 0:51 - 0:55
    things, unfortunately. You get stuff like
    this and, and,
  • 0:55 - 0:58
    you know, people - it's all about applets,
    and
  • 0:58 - 1:01
    the JVM sucks, and people, people actually
    go to
  • 1:01 - 1:03
    our code base and look for stuff like that.
  • 1:03 - 1:06
    But, I mean, the bottom line, the bottom line
  • 1:10 - 1:12
    we always try to get across is really that
  • 1:12 - 1:16
    JRuby is just Ruby. It's a Ruby implementation.
    It
  • 1:16 - 1:19
    happens to be written partially in Java. It
    happens
  • 1:19 - 1:20
    to run on the JVM. But it's just a
  • 1:20 - 1:22
    Ruby implementation.
  • 1:22 - 1:24
    So basics about JRuby, before we get into
    talking
  • 1:24 - 1:27
    about futures, where we're going with it.
    It, right
  • 1:27 - 1:30
    now it's compatible with Ruby 1.8.7, and 1.9.3.
    This
  • 1:30 - 1:32
    is gonna change in the future, as we'll talk
  • 1:32 - 1:34
    about.
  • 1:34 - 1:36
    Mostly written in Java. More and more code
    being
  • 1:36 - 1:38
    written in Ruby. But, even the Java code we
  • 1:38 - 1:42
    have is pretty clean. We've got a pretty standard
  • 1:42 - 1:45
    coding conventions that we like our committers
    and contributors
  • 1:45 - 1:47
    to follow.
  • 1:47 - 1:49
    And the coolest part about JRuby, and the
    reason
  • 1:49 - 1:51
    that most people come to JRuby is because
    the
  • 1:51 - 1:54
    entire world of the JVM is available to you.
  • 1:54 - 1:56
    The GCs that we've got available, all the
    different
  • 1:56 - 1:59
    platforms. The GIT runtime. And then of course
    all
  • 1:59 - 2:01
    of the libraries and languages that are on
    the
  • 2:01 - 2:02
    JVM.
  • 2:02 - 2:04
    So it's, it's a Ruby on top of this
  • 2:04 - 2:07
    platform that brings a lot more than just
    Ruby
  • 2:07 - 2:08
    to the table.
  • 2:08 - 2:10
    TOM ENEBO: OK. I'm gonna talk a little bit
  • 2:10 - 2:14
    about JRuby. How we version and branch and
    how
  • 2:14 - 2:18
    we've evolved our development a little bit.
    When we
  • 2:18 - 2:21
    do a significant release of JRuby, we do all
  • 2:21 - 2:24
    of our development on Master. Once we hit
    that
  • 2:24 - 2:27
    1.6.0, as you know, any project that hits
    1.6.0
  • 2:27 - 2:30
    isn't, like, quite ready to be used yet.
  • 2:30 - 2:33
    So, we usually do one or more point release
  • 2:33 - 2:35
    until we feel confident, and then we create
    a
  • 2:35 - 2:39
    maintenance branch. In the case of 1.6, we
    did
  • 2:39 - 2:43
    it after 1.6.1, JRuby 1.6 was gonna be the
  • 2:43 - 2:49
    great 1.9 release for JRuby, and it wasn't.
  • 2:49 - 2:53
    Most of the 1.9 stuff was there, except for
  • 2:53 - 2:54
    encoding, which was a-
  • 2:54 - 2:57
    C.N.: Turned out to be kind of important.
  • 2:57 - 3:01
    T.E.: A tremendous amount of work. And so
    time
  • 3:01 - 3:03
    marches on. A year later we put out a
  • 3:03 - 3:07
    preview release on 1.7. We're plugging away
    on Master,
  • 3:07 - 3:08
    working on the next great thing.
  • 3:08 - 3:11
    Oh, another five months, 1.7.0 comes out.
    So for
  • 3:11 - 3:14
    a year and a half, we're on this dual-branch
  • 3:14 - 3:17
    development mode, and what ended up happening
    is, we
  • 3:17 - 3:20
    had so much fun in master that not a
  • 3:20 - 3:23
    lot of stuff made it to 1.6, and the
  • 3:23 - 3:27
    branches kept getting further apart. And we
    did merge
  • 3:27 - 3:30
    stuff when people asked for it, but this was
  • 3:30 - 3:31
    not something that we wanted to repeat.
  • 3:31 - 3:33
    C.N.: Right. We really want to keep our releases
  • 3:33 - 3:37
    short and closer together. And, and keep fixes
    going
  • 3:37 - 3:38
    to the right places. To the, to the releases
  • 3:38 - 3:39
    people are using.
  • 3:39 - 3:43
    T.E.: So when we started working on 1.7, you'll
  • 3:43 - 3:46
    see that we didn't actually create a maintenance
    branch
  • 3:46 - 3:49
    until after 1.7.5. This was us-
  • 3:49 - 3:54
    C.N.: Right, keep it real.
  • 3:54 - 3:56
    T.E.: Yeah, I mean. It's discipline and pain.
    I
  • 3:56 - 3:57
    was trying to think of the right word to
  • 3:57 - 3:58
    represent pain.
  • 3:58 - 4:02
    C.N.: Rather than going off on, on a completely
  • 4:02 - 4:04
    new version of JRuby, we forced ourselves
    to do
  • 4:04 - 4:06
    a lot of incremental releases for 1.7, to
    keep
  • 4:06 - 4:07
    improving it.
  • 4:07 - 4:09
    T.E.: And we knew that we're gonna be working
  • 4:09 - 4:11
    on a major release. So we wanted to make
  • 4:11 - 4:13
    sure that things are really solid by the time
  • 4:13 - 4:14
    we started doing that.
  • 4:14 - 4:17
    And in fact we almost did this at 1.7.3,
  • 4:17 - 4:19
    then realized that we were still missing encoding
    work
  • 4:19 - 4:23
    on zlib. And coding's really hard.
  • 4:25 - 4:26
    So the other things that we're gonna try to
  • 4:26 - 4:29
    do to try to make this dual-branch development
    work
  • 4:29 - 4:31
    better, is we're gonna make sure that we put
  • 4:31 - 4:34
    out a release at least every three weeks.
  • 4:34 - 4:36
    This is to keep us honest. If we go
  • 4:36 - 4:38
    and put out a release in three weeks and
  • 4:38 - 4:39
    it only has one fix in it, then we're
  • 4:39 - 4:42
    not really doing our job, so. This'll keep
    us
  • 4:42 - 4:43
    honest.
  • 4:43 - 4:45
    And the other big change is that anything
    that
  • 4:45 - 4:49
    involves compatibility, we're gonna apply
    to 1.7 first. And
  • 4:49 - 4:53
    we're constantly merging back to Master. Things'll
    be golden.
  • 4:53 - 4:58
    I think we've finally found our sweet spot
    here.
  • 4:58 - 5:01
    So let's talk about the next major release.
  • 5:01 - 5:03
    One big change, Charlie will show some stats
    in
  • 5:03 - 5:06
    a little bit, but we're only gonna support
    Ruby
  • 5:06 - 5:09
    2 point 1. It's coming out sometime next year.
  • 5:09 - 5:11
    It should line up good with MRI.
  • 5:11 - 5:14
    This is gonna be awesome. Supporting multiple
    modes of
  • 5:14 - 5:17
    Ruby at the same time is really painful.
  • 5:17 - 5:20
    We're probably gonna be Java 7 and higher.
    If
  • 5:20 - 5:23
    there's any people that use Java 6, and you're
  • 5:23 - 5:25
    not gonna be able to migrate by next year,
  • 5:25 - 5:27
    just talk to us. We want to hear who
  • 5:27 - 5:29
    those people are and what your stories are.
  • 5:29 - 5:32
    We want to be modular, both at a packaging
  • 5:32 - 5:36
    level - cause platforms like Android, they
    want to
  • 5:36 - 5:38
    have as small a jar as possible, and also
  • 5:38 - 5:41
    at the source level, because things like Google
    app
  • 5:41 - 5:44
    engine, they don't support sockets. So they
    shouldn't have
  • 5:44 - 5:48
    to compile against that.
  • 5:48 - 5:51
    Look at this picture. And now look at this
  • 5:51 - 5:53
    next slide.
  • 5:53 - 5:56
    We're gonna be breaking lots of APIs. This
    is
  • 5:56 - 5:58
    the first time that we've actually decided
    to break
  • 5:58 - 6:01
    a lot of APIs. It's been ten years, or
  • 6:01 - 6:05
    maybe more than ten years. So we're going
    to
  • 6:05 - 6:07
    just clean up all the crap that we've hated
  • 6:07 - 6:09
    for ten years, and we're gonna have a lot
  • 6:09 - 6:10
    of fun doing it.
  • 6:10 - 6:14
    C.N.: This mostly affects, like, JRuby Java-based
    extensions. Obviously
  • 6:14 - 6:18
    the Ruby compatibility won't hurt at all,
    but libraries
  • 6:18 - 6:20
    that are written in Java for JRuby may have
  • 6:20 - 6:21
    to make some changes.
  • 6:21 - 6:22
    T.E.: And we have a plan for reducing the
  • 6:22 - 6:25
    pain with regards to embedding, and I'll talk
    about
  • 6:25 - 6:28
    that a little bit later. And we're also gonna
  • 6:28 - 6:30
    have a brand new runtime, which we'll talk
    about
  • 6:30 - 6:32
    later.
  • 6:32 - 6:34
    So I haven't said what the major version number
  • 6:34 - 6:37
    is yet. The natural one would have been 1
  • 6:37 - 6:39
    point 8, but JRuby 1 point 8, which supports
  • 6:39 - 6:42
    Ruby 2 point 1, would have been kind of
  • 6:42 - 6:45
    weird. 1 point 9, 2 point 0, same thing.
  • 6:45 - 6:47
    2 point 1? That one actually does kind of
  • 6:47 - 6:49
    make sense, cause we will support 2 point
    1,
  • 6:49 - 6:52
    but then we'd release a 2 point 2 before
  • 6:52 - 6:56
    MRI did, and that would be weird. So.
  • 6:56 - 6:58
    We should have did this for our version number
  • 6:58 - 7:00
    - we should have went from 1.7 to 8,
  • 7:00 - 7:06
    like Java. But we're weird like that. We,
    well,
  • 7:06 - 7:08
    we'll see.
  • 7:08 - 7:09
    We could have picked X and went to ten
  • 7:09 - 7:13
    like Apple.
  • 7:13 - 7:15
    We kept joking. Ah, we'll just call it nine
  • 7:15 - 7:16
    thousand.
  • 7:22 - 7:25
    I hope people can hear this.
  • 7:25 - 7:26
    -VIDEO-
  • 7:26 - 7:27
    Character: What does the scouter say about
    his power
  • 7:27 - 7:28
    level?
  • 7:28 - 7:31
    OTHER: It's over nine thousand!!!
  • 7:31 - 7:33
    Character: What, nine thousand? There is no
    way that
  • 7:33 - 7:35
    can be right!
  • 7:37 - 7:40
    T.E.: OK, and if you couldn't hear that, he
  • 7:40 - 7:45
    said it's over nine thousand.
  • 7:45 - 7:48
    But our next version is actually JRuby 9000.
  • 7:54 - 7:56
    And for those people who don't like it, it's
  • 7:56 - 7:58
    just a number. Get over it.
  • 7:58 - 8:03
    C.N.: Now that - the work on JRuby 9000's
  • 8:03 - 8:05
    actually already started. It's been going
    faster than we
  • 8:05 - 8:09
    expected. This is just some, some simple stats
    comparing
  • 8:09 - 8:12
    the JRuby 1.7 line with Master. And we're
    stripping
  • 8:12 - 8:16
    out a ton of code by removing 1.8 support,
  • 8:16 - 8:18
    removing, not having two or three copies of
    standard
  • 8:18 - 8:20
    library.
  • 8:20 - 8:23
    Getting the whole of JRuby much smaller. Probably
    the
  • 8:23 - 8:26
    best one here is the, the complete jar, which
  • 8:26 - 8:29
    is JRuby plus the entire standard library
    all in
  • 8:29 - 8:32
    one file, is already down by about four meg,
  • 8:32 - 8:34
    so we're, we're getting better and better
    at shrinking
  • 8:34 - 8:35
    down the runtime.
  • 8:35 - 8:38
    We'll talk a little bit about what we're doing
  • 8:38 - 8:40
    to improve the ecosystem going forward. Probably
    the most
  • 8:40 - 8:44
    difficult part of developing JRuby, and we're
    definitely spent
  • 8:44 - 8:47
    the most amount of time, is simply on compatibility.
  • 8:47 - 8:50
    We're constantly chasing a moving target - MRI,
    which
  • 8:50 - 8:55
    has, at various times, had very fast development
    progress,
  • 8:55 - 8:56
    added large features.
  • 8:56 - 8:58
    And so we've always kind of been trying to
  • 8:58 - 9:01
    catch up. What we're hoping is that with JRuby
  • 9:01 - 9:03
    9000, we'll be able to match directly up with
  • 9:03 - 9:06
    the 2 point 1 compatibility, hopefully right
    around when
  • 9:06 - 9:09
    they do 2 point 1 release of MRI.
  • 9:09 - 9:11
    We'll have all the features implemented. And
    then we'll
  • 9:11 - 9:14
    be at our leisure to release or continue working
  • 9:14 - 9:17
    on performance runtime stuff. But hopefully
    now, being able
  • 9:17 - 9:19
    to stay in lock step with MRI and the
  • 9:19 - 9:21
    features that they add.
  • 9:21 - 9:22
    So the things that we know are still missing.
  • 9:22 - 9:26
    From 1 point 9, spawn plus all of the
  • 9:26 - 9:29
    different file opening options and redirects
    and other things.
  • 9:29 - 9:31
    There's a lot of those pieces missing. Largely
    missing
  • 9:31 - 9:35
    because the JVMs own process management APIs
    don't support
  • 9:35 - 9:37
    most of them. It's very difficult to do them.
  • 9:37 - 9:39
    We'll probably have to do a native call-out
    to
  • 9:39 - 9:42
    do these in full, have full support for them.
  • 9:42 - 9:44
    We do have full transcoding support now, and
    it
  • 9:44 - 9:47
    does work well. We fixed a ton of issues
  • 9:47 - 9:49
    and did a complete rewrite of IO transcoding
    and
  • 9:49 - 9:53
    coding stuff for 1.7.5 that seems to be doing
  • 9:53 - 9:55
    well. We haven't gotten any real major issues
    with
  • 9:55 - 9:56
    it.
  • 9:56 - 10:00
    But we're using all the JVMs character-based
    UTF16 transcoders,
  • 10:00 - 10:03
    so everything has to go to UTF16 and then
  • 10:03 - 10:05
    back out to the target encoding. That's overhead
    we'd
  • 10:05 - 10:08
    like to eliminate by porting over the same
    byte
  • 10:08 - 10:11
    array based transcoding support that MRI has.
  • 10:11 - 10:13
    And that's probably gonna come up soon.
  • 10:13 - 10:15
    2 point 1 stuff that we know we're missing.
  • 10:15 - 10:17
    Prepend. We don't have it in there yet. Shouldn't
  • 10:17 - 10:20
    be too difficult. Refinements are going to
    be officially
  • 10:20 - 10:24
    a feature in 2.1. I've worked pretty closely
    with
  • 10:24 - 10:25
    a lot of the MRI folks to try and
  • 10:25 - 10:27
    strip down the feature a little bit, make
    it
  • 10:27 - 10:30
    not as invasive, not as damaging to performance.
    And
  • 10:30 - 10:33
    I think we're, we're confident now that we
    can
  • 10:33 - 10:35
    implement it in JRuby without a major impact.
  • 10:35 - 10:37
    But it's not there yet. We'll have that hopefully
  • 10:37 - 10:40
    by the time MRI 2 point 1 comes out.
  • 10:40 - 10:42
    And then there's enumerator enhancements that
    are not quite
  • 10:42 - 10:45
    there yet. Size is there, lazy stuff - size
  • 10:45 - 10:48
    isn't there, lazy is. Little bits and pieces
    from
  • 10:48 - 10:50
    2 point 1 that we, we still need to
  • 10:50 - 10:51
    implement.
  • 10:51 - 10:53
    We're always trying to work on improving the,
    the
  • 10:53 - 10:57
    platform in general. Not just for JRuby either.
    For
  • 10:57 - 10:59
    example, lots of gems for thread safety - I'll
  • 10:59 - 11:02
    talk about later. Gems, like FFI, for calling
    out
  • 11:02 - 11:06
    to native libraries. Database access, image
    stuff. All this
  • 11:06 - 11:08
    thing- all these things to fill in the blanks
  • 11:08 - 11:10
    for JRuby users.
  • 11:10 - 11:14
    We're constantly working with gem authors
    to improve performance
  • 11:14 - 11:16
    of their libraries on JRuby and performance
    in general,
  • 11:16 - 11:20
    in a lot of cases. Fixed threading problems.
    More
  • 11:20 - 11:23
    and more Ruby gem authors and library authors
    have
  • 11:23 - 11:25
    started to pay attention to threading, testing
    stuff on
  • 11:25 - 11:28
    JRuby, testing in concurrent situations. So
    we're looking pretty
  • 11:28 - 11:31
    good in that area, too.
  • 11:31 - 11:33
    Probably the biggest thing is trying to get
    more
  • 11:33 - 11:37
    Rubyists testing their stuff on JRuby. Travis
    is a
  • 11:37 - 11:40
    nice, easy way to do it, otherwise, an RVM
  • 11:40 - 11:42
    set-up, getting something local that you can
    test on,
  • 11:42 - 11:44
    to help improve the whole platform.
  • 11:44 - 11:47
    We're also going to continue trying to improve
    how
  • 11:47 - 11:50
    closely we work with MRI. I've been active
    on
  • 11:50 - 11:52
    a lot of issues. All of JRuby team members
  • 11:52 - 11:55
    have been active on issues in the Ruby bug
  • 11:55 - 11:59
    tracker, especially feature-related futures
    for Ruby that are going
  • 11:59 - 12:00
    to affect JRuby.
  • 12:00 - 12:03
    Trying to do more on that. Especially since
    JRuby's
  • 12:03 - 12:05
    kind of leaned away on concurrency and parallel
    execution
  • 12:05 - 12:08
    of Ruby code, trying to push that forward
    and,
  • 12:08 - 12:10
    and take the lead on figuring out how that's
  • 12:10 - 12:11
    supposed to look.
  • 12:11 - 12:13
    I'm actually a committer on MRI, and I've
    fixed
  • 12:13 - 12:16
    a few things. Hopefully doing more of that
    in
  • 12:16 - 12:18
    the future, try and clean up standard library.
    Get
  • 12:18 - 12:22
    some threading utilities in there, get some
    cleanup done.
  • 12:22 - 12:23
    And, and just in general trying to help improve
  • 12:23 - 12:26
    the process of evolving Ruby based on how
    we
  • 12:26 - 12:27
    do JRuby development.
  • 12:27 - 12:30
    So let's talk a little bit about performance
    that
  • 12:30 - 12:33
    we're gonna work on in the future. So there's
  • 12:33 - 12:35
    a lot that we can do to continue making
  • 12:35 - 12:38
    JRuby faster, make Ruby in general faster.
  • 12:38 - 12:40
    The challenges are, we've got lots and lots
    of
  • 12:40 - 12:44
    dynamic calls, very dynamic object structures,
    lots of indirection
  • 12:44 - 12:48
    around. The structure of the objects isn't
    even fixed
  • 12:48 - 12:51
    at startup time. It's defined as instance
    variables up
  • 12:51 - 12:53
    here. So there's more and more we need to
  • 12:53 - 12:54
    do.
  • 12:54 - 12:56
    The first step of what we do as far
  • 12:56 - 12:58
    as performance is basically just compiling
    things down to
  • 12:58 - 13:02
    byte code. The JVM likes byte code, obviously,
    and
  • 13:02 - 13:05
    that's what it optimizes. So that's the simple
    first
  • 13:05 - 13:06
    step.
  • 13:06 - 13:09
    What we can do more of here is generating
  • 13:09 - 13:12
    real classes for the Ruby classes that you
    create,
  • 13:12 - 13:15
    so the JVM sees a normal Java class object.
  • 13:15 - 13:18
    Generating instance variable tables that are
    directly in the
  • 13:18 - 13:21
    object rather than ass a tag-a-long data structure.
    Shrinking
  • 13:21 - 13:23
    everything down, reducing the amount of indirection
    that we
  • 13:23 - 13:25
    have.
  • 13:25 - 13:28
    We've also been hitting invoke dynamic pretty
    hard. Invoke
  • 13:28 - 13:31
    dynamic is a feature added to Java 7, that
  • 13:31 - 13:34
    basically makes it possible for dynamic languages
    to plug
  • 13:34 - 13:38
    directly into the JVM and optimize, like,
    any statically
  • 13:38 - 13:39
    typed language.
  • 13:39 - 13:42
    It has a byte code, of course, that represents
  • 13:42 - 13:46
    a dynamic call, and then a series of handles
  • 13:46 - 13:50
    and, and manipulators, and argument modifiers
    to basically describe
  • 13:50 - 13:53
    how to do the dynamic call in a way
  • 13:53 - 13:54
    the JVM can optimize straight through.
  • 13:54 - 13:57
    Now does this actually work? Does this actually
    optimize
  • 13:57 - 13:57
    well?
  • 13:57 - 14:00
    Well, this is one of the bench marks I've
  • 14:00 - 14:03
    been showing. It's, the red-black tree C-extension,
    and the
  • 14:03 - 14:07
    Java extension, compared to pure Ruby version.
  • 14:07 - 14:09
    So if we look at Ruby 1.9 and 2.0
  • 14:09 - 14:12
    with the pure Ruby version, Ruby 2 does a
  • 14:12 - 14:15
    ton of stuff to improve performance. Some
    of these
  • 14:15 - 14:17
    are inspired by what we've done in JRuby,
    reducing
  • 14:17 - 14:20
    call overhead and so on, but there's definitely
    a
  • 14:20 - 14:23
    good improvement in 2.0 and 2.1 as far as
  • 14:23 - 14:25
    straight-line performance of Ruby code.
  • 14:25 - 14:28
    Maglov and MacRuby, I don't know if anybody's
    using
  • 14:28 - 14:31
    those lately. They, they do better. They have
    actually
  • 14:31 - 14:34
    git optimizations that they do, and then are
    able
  • 14:34 - 14:35
    to be about twice as fast as Ruby 2.0
  • 14:35 - 14:39
    just by doing some fairly simply gitting.
  • 14:39 - 14:42
    Rubinius has more of an optimizing git, and
    so
  • 14:42 - 14:44
    it, running Ruby code, it actually starts
    to get
  • 14:44 - 14:47
    comparable to the CRuby versions running with
    the C
  • 14:47 - 14:48
    extension.
  • 14:48 - 14:50
    The overhead of the Ruby code that wraps the
  • 14:50 - 14:53
    C extension, and the call-outs to the C extension
  • 14:53 - 14:56
    start to become more overhead for MRI here.
    And
  • 14:56 - 14:59
    now these are the cool ones actually.
  • 14:59 - 15:02
    So this is JRuby on invoke dynamic on Java
  • 15:02 - 15:05
    7 or 8, with the pure Ruby version in
  • 15:05 - 15:08
    the gray here. And it's actually, you know,
    not
  • 15:08 - 15:11
    quite twice as fast as Ruby 2.0 with the
  • 15:11 - 15:13
    C extension. So we're actually able to run
    the
  • 15:13 - 15:16
    Ruby version of the red-black tree extension,
    or red/black
  • 15:16 - 15:19
    tree library, almost as fast, a lot faster
    in
  • 15:19 - 15:21
    some cases, as the C extension.
  • 15:21 - 15:23
    And then of course JRuby in the Java extension.
  • 15:23 - 15:25
    Since it all just looks like Java, regardless
    of
  • 15:25 - 15:28
    whether you're calling into a Java library
    or calling
  • 15:28 - 15:30
    from Ruby code, the JVM is able to do
  • 15:30 - 15:33
    a significant optimization on that.
  • 15:33 - 15:36
    Now, this is great, and invoke dynamic definitely
    works,
  • 15:36 - 15:37
    as far as the performance you can get out
  • 15:37 - 15:41
    of it. But there is a caveat here.
  • 15:41 - 15:42
    So invoke dynamic, when it first came out
    in
  • 15:42 - 15:45
    Java 7, was very slow. It got fast in
  • 15:45 - 15:48
    the first, the, the second update to Java
    7,
  • 15:48 - 15:51
    but that was also broken. There was some severe
  • 15:51 - 15:54
    issues that, when you deployed in production
    it wouldn't
  • 15:54 - 15:55
    run properly.
  • 15:55 - 15:59
    7, update 40, rewrote it, and it is now
  • 15:59 - 16:02
    100% compatible, 100% no bugs with it. But
    it's
  • 16:02 - 16:05
    very slow to warm up, and it uses significantly
  • 16:05 - 16:08
    more memory than the original implementation
    did.
  • 16:08 - 16:11
    So it's probably going to settle more on Java
  • 16:11 - 16:13
    8. We have had a few users using Java
  • 16:13 - 16:15
    8 with invoke dynamic, not reporting any of
    the
  • 16:15 - 16:18
    issues that we had during the Java 7 time
  • 16:18 - 16:18
    frame.
  • 16:18 - 16:20
    So if you're interested in getting the best
    performance
  • 16:20 - 16:22
    out of it, the Java 8 preview builds would
  • 16:22 - 16:24
    be a good way to test it out.
  • 16:24 - 16:26
    Now, because of all these issues we continue
    to
  • 16:26 - 16:28
    look at other options. One of them that came
  • 16:28 - 16:31
    up recently is a couple non-JVM git projects
    out
  • 16:31 - 16:34
    of Oracle, call- there's one called Graal,
    which is
  • 16:34 - 16:38
    basically an API directly to the git in the
  • 16:38 - 16:41
    JVM, and Truffle, which allows you to take
    languages
  • 16:41 - 16:45
    AST, abstract syntax tree, and, and basically
    convert it
  • 16:45 - 16:48
    directly into Graal calls, and optimize it
    down.
  • 16:48 - 16:51
    Now the early numbers on this have looked
    good.
  • 16:51 - 16:53
    Oracle did spend about six months doing a
    proof
  • 16:53 - 16:57
    of concept Ruby implementation on top of Truffle.
    That's
  • 16:57 - 17:00
    about five or six times faster than JRuby,
    but
  • 17:00 - 17:03
    the problem here is that they've only got
    about
  • 17:03 - 17:06
    half of the, in this case, Ruby spec passing,
  • 17:06 - 17:08
    and there's a lot more that needs to be
  • 17:08 - 17:09
    done. There's probably two or three years
    worth of
  • 17:09 - 17:11
    work to get that going.
  • 17:11 - 17:13
    What we're hoping is that maybe we'll have
    some
  • 17:13 - 17:16
    time to explore building a Truffle of Graal
    based
  • 17:16 - 17:17
    backend in JRuby itself.
  • 17:17 - 17:19
    T.E.: And, and once you add some of the
  • 17:19 - 17:22
    extra vagries of what Ruby does, that performance
    is
  • 17:22 - 17:23
    probably going to drop.
  • 17:23 - 17:25
    C.N.: Yeah, exactly. There's a lot of other
    stuff
  • 17:25 - 17:26
    that they have to put in there. And, and
  • 17:26 - 17:30
    these libraries are a big part of performance,
    too.
  • 17:30 - 17:30
    So.
  • 17:30 - 17:33
    And, I'll hand it over here to talk a
  • 17:33 - 17:34
    little bit more about the new IR-based compiler
    that
  • 17:34 - 17:37
    we're also working on.
  • 17:37 - 17:41
    T.E.: Yeah, so, IR stands for internal representation,
    which
  • 17:41 - 17:44
    is probably not the most inventive name that
    we
  • 17:44 - 17:46
    could have come up with. But it's our new
  • 17:46 - 17:53
    runtime. Subramanya Swarovski created the
    bulk of IR up
  • 17:54 - 17:56
    to this point. He's the guy who got a
  • 17:56 - 18:02
    PhD in writing a Java optimizing compiler.
  • 18:02 - 18:05
    And he basically created an architecture that's
    very similar
  • 18:05 - 18:08
    to a compiler architecture, if you read like
    the
  • 18:08 - 18:13
    Dragon book, or took a course at university.
  • 18:13 - 18:15
    And we really wanted to create a new runtime
  • 18:15 - 18:17
    because we were fed-up with trying to do these
  • 18:17 - 18:23
    optimizations directly from AST. We also wanted
    something that
  • 18:23 - 18:25
    we weren't going to want to rewrite five years
  • 18:25 - 18:27
    from now. So we wanted it to be easy
  • 18:27 - 18:30
    to go and plug in to optimizations and have
  • 18:30 - 18:33
    a lot of growth.
  • 18:33 - 18:35
    So here's what IR sort of looks like at
  • 18:35 - 18:40
    the top, for JRuby 1.7 and below we'll, will
  • 18:40 - 18:43
    lex and parse Ruby code and generate an abstract
  • 18:43 - 18:46
    syntax tree, and then will either interpret
    that until
  • 18:46 - 18:49
    it gets warm, and then we'll translate it
    to
  • 18:49 - 18:53
    Java byte code as part of a git, but
  • 18:53 - 18:57
    in the new IR landscape for 9k, we'll perform
  • 18:57 - 19:01
    some semantic analysis and translate that
    syntax tree into
  • 19:01 - 19:04
    a set of instructions and operands that represent
    Ruby
  • 19:04 - 19:07
    semantics, instead of just syntax.
  • 19:07 - 19:09
    We'll create some supplementary data centers,
    like a control
  • 19:09 - 19:13
    flow graph. After that, we can run a series
  • 19:13 - 19:17
    of optimizations on that, create some more
    data structures,
  • 19:17 - 19:22
    change some of these existing ones, and then
    hopefully
  • 19:22 - 19:24
    we'll build a maintain a very thin layer for
  • 19:24 - 19:29
    an interpreter. Pretty simple byte code generation
    layer, and
  • 19:29 - 19:31
    we'll be able to expand it out later on
  • 19:31 - 19:32
    to things like Dalvik.
  • 19:32 - 19:33
    C.N.: Ideally trying to do as many optimizations
    as
  • 19:33 - 19:36
    possible, before we even get to the point
    of
  • 19:36 - 19:39
    generating byte code.
  • 19:39 - 19:42
    T.E.: So here's our first look at what the
  • 19:42 - 19:45
    instructions are. I'll just go down a few
    of
  • 19:45 - 19:46
    these.
  • 19:46 - 19:47
    At the very top, we make sure that there's
  • 19:47 - 19:52
    two required arguments with check_arity. The
    next three instructions
  • 19:52 - 19:55
    we assign the parameters, a, b, but then we
  • 19:55 - 19:58
    also assign the closure, in case someone actually
    supplied
  • 19:58 - 20:00
    a block to it.
  • 20:00 - 20:02
    Down at line six you can see c equals
  • 20:02 - 20:06
    one, looks like the left side, and lines eight
  • 20:06 - 20:10
    and nine represent d equals a plus c. This
  • 20:10 - 20:13
    one doesn't quite read as nice, but it's still
  • 20:13 - 20:18
    pretty simple.
  • 20:18 - 20:20
    We can do all the optimizations that you would
  • 20:20 - 20:23
    expect if you took a compiler's course. If
    we
  • 20:23 - 20:25
    find code that we can remove that won't effect
  • 20:25 - 20:29
    how the program runs, we can just eliminate
    it.
  • 20:29 - 20:32
    If we, if we see a constant value that
  • 20:32 - 20:35
    we know doesn't change, we can just propagate
    that
  • 20:35 - 20:37
    to where it's used and get rid of the,
  • 20:37 - 20:40
    the dereferencing from the variable.
  • 20:40 - 20:42
    We can inline methods and blocks that we're
    not
  • 20:43 - 20:44
    actually using a lot yet.
  • 20:44 - 20:47
    C.N.: We do have some early inlines for it
  • 20:47 - 20:49
    though, so it is possible we have managed
    to
  • 20:49 - 20:49
    make it work.
  • 20:49 - 20:51
    T.E.: Oh it, it totally works. It's just figuring
  • 20:51 - 20:53
    out when to do it is, is a much
  • 20:53 - 20:57
    harder problem than we realized.
  • 20:57 - 20:59
    So here, if we run a couple passes, you
  • 20:59 - 21:01
    can see that we got rid of about half
  • 21:01 - 21:03
    the lines of code. You can see we didn't
  • 21:03 - 21:06
    use closure, so we just eliminated that, same
    with
  • 21:06 - 21:12
    the variable b. On line six equals one, we
  • 21:12 - 21:15
    know that it never changes, so we propagate
    the
  • 21:15 - 21:18
    value one down to the plus call, so now
  • 21:18 - 21:20
    we're doing a plus one instead of a plus
  • 21:20 - 21:20
    c.
  • 21:20 - 21:27
    And, in general, we're reducing overhead.
    We have things
  • 21:27 - 21:31
    like block that is given, littered through
    our code
  • 21:31 - 21:35
    base. This is a check that's really fast.
    But
  • 21:35 - 21:38
    it's not free. If you compare that to the
  • 21:38 - 21:43
    dead code elimination aspect of receiving
    this block as
  • 21:43 - 21:45
    an instruction, if we can eliminate it, then
    we're
  • 21:45 - 21:48
    doing absolutely no work, and no work's better
    than
  • 21:48 - 21:49
    some work.
  • 21:49 - 21:50
    C.N.: And then as we're able to do some
  • 21:50 - 21:53
    more inlining, a lot of these same optimizations
    will
  • 21:53 - 21:56
    propagate through multiple methods. Like if
    it turns out
  • 21:56 - 21:59
    that a plus one, a was also a fixnum,
  • 21:59 - 22:01
    while maybe we inline it and just turns in
  • 22:01 - 22:03
    to it at that point.
  • 22:03 - 22:04
    So there's a lot of stuff that we can
  • 22:04 - 22:07
    do to, to optimize through code once we get
  • 22:07 - 22:07
    the inlining working.
  • 22:07 - 22:09
    T.E.: And you can just keep reapplying some
    of
  • 22:09 - 22:11
    the same optimizations after that inlining
    and just-
  • 22:11 - 22:12
    C.N.: Right.
  • 22:12 - 22:13
    T.E.: -keeps boiling down.
  • 22:13 - 22:15
    C.N.: That's the black magic of compiler optimization.
    When
  • 22:15 - 22:17
    do you stop?
  • 22:17 - 22:20
    All right, so concurrency-wise, most folks
    know that this
  • 22:20 - 22:24
    is the, the situation in general. Ruby 1.8
    was
  • 22:24 - 22:27
    green-threaded, Ruby 1.9 plus all have actual
    native threads
  • 22:27 - 22:29
    but don't allow parallel execution because
    of the global
  • 22:29 - 22:31
    lock.
  • 22:31 - 22:32
    Whereas on JRuby, because it's on the JVM,
    the
  • 22:32 - 22:35
    JVM's had real parallel threads for a long
    time,
  • 22:35 - 22:38
    we do actually have real threads, you can
    actually
  • 22:38 - 22:42
    saturate an entire machine with just one JRuby
    process.
  • 22:42 - 22:44
    And where this really comes into play is the
  • 22:44 - 22:47
    cost of deploying wide applications for a
    lot of
  • 22:47 - 22:52
    users. You look at a ten-way concurrent in
    MRI,
  • 22:52 - 22:54
    each process is maybe a hundred, two hundred
    megabytes.
  • 22:54 - 22:57
    If it's two hundred megabytes, that's two
    gigabytes of
  • 22:57 - 22:59
    memory that you need to allocate. And that's
    not
  • 22:59 - 23:01
    a, that's not a trivial instance. It's not
    a
  • 23:01 - 23:02
    huge on.
  • 23:02 - 23:03
    But then, what if we need to scale this
  • 23:03 - 23:05
    thing up? And what if we need to handle
  • 23:05 - 23:07
    a hundred concurrent users? Well, then we
    need to
  • 23:07 - 23:10
    have a hundred-way concurrency in MRI, which
    means a
  • 23:10 - 23:12
    hundred processes. Now we're getting into
    twenty gig. This
  • 23:12 - 23:15
    is getting into the very high, very expensive
    end
  • 23:15 - 23:18
    of, for example EC2 instances.
  • 23:18 - 23:21
    We recently had someone make a migration to
    JRuby
  • 23:21 - 23:24
    and save something like fifteen thousand dollars
    a month
  • 23:24 - 23:27
    by moving from a whole set of extra larges,
  • 23:27 - 23:29
    down to like, five mediums.
  • 23:29 - 23:31
    And so there are real, tangible benefits to
    making
  • 23:31 - 23:34
    a move to JRuby and, and getting threading
    working
  • 23:34 - 23:36
    well for your application.
  • 23:36 - 23:38
    Look at how it is in JRuby. One instance,
  • 23:38 - 23:40
    it's going to be a little bit more, a
  • 23:40 - 23:42
    little bit larger as a base cost, but you
  • 23:42 - 23:44
    can handle ten instances, ten concurrent,
    you can handle
  • 23:44 - 23:47
    a hundred concurrent. You can handle whatever
    the machine's
  • 23:47 - 23:49
    capable of handling, pretty much with one
    process. Maybe
  • 23:49 - 23:51
    you have one for fall back, but it's, it's
  • 23:51 - 23:55
    a tremendous difference as far as scaling.
  • 23:55 - 23:57
    But there's challenges here, too, and this
    is where
  • 23:57 - 23:59
    a lot of the future work needs to come
  • 23:59 - 24:01
    in. The Ruby world and the Ruby libraries
    out
  • 24:01 - 24:03
    there are still kind of growing into concurrency,
    growing
  • 24:03 - 24:06
    into parallelism. And there hasn't been a
    big emphasis
  • 24:06 - 24:09
    on threading or concurrent execution in the
    Ruby world.
  • 24:09 - 24:10
    And so there's more that we need to do.
  • 24:10 - 24:12
    We need tools to make it easier. We need
  • 24:12 - 24:14
    a lot, we need to help make these libraries
  • 24:14 - 24:15
    thread safe.
  • 24:15 - 24:17
    These are some of the key unsafe operations
    that
  • 24:17 - 24:21
    you're gonna see in, in libraries that aren't
    thread
  • 24:21 - 24:24
    safe. Concurrent read and write on, on data
    structures,
  • 24:24 - 24:26
    like array, hash - those are not guaranteed
    to
  • 24:26 - 24:29
    be thread safe. So if you're not doing mutexing
  • 24:29 - 24:30
    around those they can be a problem.
  • 24:30 - 24:33
    A lot of people don't realize that, that calls
  • 24:33 - 24:38
    like this are not done automatically in any
    implementation.
  • 24:38 - 24:40
    There's a possibility of a thread jumping
    in there
  • 24:40 - 24:42
    and doing the same increment at the same time.
  • 24:42 - 24:44
    You get different results out of it.
  • 24:44 - 24:47
    In this one, if my cache really, really needs
  • 24:47 - 24:49
    to be allocated only once, this is not a
  • 24:49 - 24:51
    safe way to do it, because it's very possible
  • 24:51 - 24:53
    that you may allocate two of them if two
  • 24:53 - 24:56
    threads get to that code at the same time.
  • 24:56 - 24:58
    Thread pooling's tough, we need better libraries
    to do
  • 24:58 - 25:01
    that. Ideally some things that start to get
    into
  • 25:01 - 25:04
    Ruby core. And then just coordinating between
    threads. Better
  • 25:04 - 25:07
    ways of communicating and synchronizing threads
    together.
  • 25:07 - 25:09
    So a few gems that we, we, we like,
  • 25:09 - 25:12
    some of these we maintain, some are from friends
  • 25:12 - 25:16
    of ours. The thread_safe gem provides concurrency-safe
    hash and
  • 25:16 - 25:19
    array. It also provides, I'm not showing here,
    a
  • 25:19 - 25:23
    cache class, which is very, it's hash-like,
    but it
  • 25:23 - 25:25
    uses some of the techniques that the, the
    Java
  • 25:25 - 25:29
    concurrency engineers use for concurrent hash
    map to do
  • 25:29 - 25:31
    fast multi-threaded hash map implementation.
  • 25:31 - 25:34
    But otherwise pretty simple. You construct
    it, you use
  • 25:34 - 25:36
    it like a normal hash almost. And it works
  • 25:36 - 25:39
    pretty much the same way.
  • 25:39 - 25:43
    Hamster is a set of persistent collections
    for Ruby.
  • 25:43 - 25:45
    The difference with persistent collections
    is that you never
  • 25:45 - 25:49
    mutate it in place. Every mutation operation
    gives you
  • 25:49 - 25:52
    a new reference, which is that old collection
    with
  • 25:52 - 25:54
    this change applied to it.
  • 25:54 - 25:56
    So the object you have in hand is always
  • 25:56 - 25:59
    basically read-only, and you know that no
    other mutations
  • 25:59 - 26:02
    happening in the system will impact your reads
    of
  • 26:02 - 26:03
    it.
  • 26:03 - 26:04
    So it's a hundred percent safe as far as
  • 26:04 - 26:06
    concurrency goes, and the nice thing about
    it is
  • 26:06 - 26:09
    it avoids any sort of locking or magic tricks
  • 26:09 - 26:12
    under the cover. You just getting a new view
  • 26:12 - 26:14
    of this data structure that everyone still
    has their
  • 26:14 - 26:14
    old view of.
  • 26:14 - 26:18
    I won't walk through the whole example here
    but,
  • 26:18 - 26:21
    it's, it's fairly simple to use. Every other
    mutation,
  • 26:21 - 26:23
    you just assign the result and then you've
    got
  • 26:23 - 26:25
    your new collection as a result.
  • 26:25 - 26:28
    So for those atomic updates, or equals, plus
    equals
  • 26:28 - 26:32
    and so on, there's the atomic gem. Atomic
    gem
  • 26:32 - 26:34
    basically gives you a wrapped value that you
    can
  • 26:34 - 26:38
    do atomic updates to. Increment it atomically,
    perform some
  • 26:38 - 26:42
    Ruby action atomically, and will only happen
    if nobody
  • 26:42 - 26:44
    else jumps in. So, so you'll get the atomic
  • 26:44 - 26:47
    right. Other threads will have to retry again.
    But
  • 26:47 - 26:49
    it guarantees that no one's gonna step on
    each
  • 26:49 - 26:50
    other.
  • 26:50 - 26:52
    This is a simple example. We create an atomic
  • 26:52 - 26:55
    object at the top, which is just a fixnum
  • 26:55 - 26:57
    zero. We can get the value out, we can
  • 26:57 - 27:00
    swap it for another value. And then the more
  • 27:00 - 27:03
    interesting one's doing compare and swap,
    if the existing
  • 27:03 - 27:06
    value is two, put three in there. And then
  • 27:06 - 27:08
    the second line, since we know it's not two
  • 27:08 - 27:10
    anymore, that's not gonna happen. This is
    how we
  • 27:10 - 27:12
    keep threads from stepping on each other's
    updates.
  • 27:12 - 27:14
    You can try to make an update, only if
  • 27:14 - 27:18
    it's the same state you expect. Down here,
    doing
  • 27:18 - 27:22
    more advanced atomic updates. Update with
    a block will
  • 27:22 - 27:24
    only make that change if no other thread jumps
  • 27:24 - 27:25
    in there at the same time.
  • 27:25 - 27:28
    And if the, if you need the, if another
  • 27:28 - 27:31
    thread jumps in, it'll try and make the change.
  • 27:31 - 27:33
    It'll eith- in this case, it'll redo that
    block
  • 27:33 - 27:35
    and down here it'll raise an error. You can
  • 27:35 - 27:37
    decide whether you want to try to continue
    doing
  • 27:37 - 27:40
    this update.
  • 27:40 - 27:42
    So the bottom line for these libraries is
    that
  • 27:42 - 27:45
    concurrency really can work in Ruby, and there's
    a
  • 27:45 - 27:48
    lot of people doing highly concurrent applications
    on JRuby
  • 27:48 - 27:50
    right now. But we need the right kind of
  • 27:50 - 27:52
    tools and the right patterns to do it.
  • 27:52 - 27:55
    Immutability really helps. Having some of
    these sort of
  • 27:55 - 27:58
    data structures helps. And testing on JRuby
    is really
  • 27:58 - 28:01
    the only way to know if your library is
  • 28:01 - 28:03
    gonna be thread safe. We've got the most extensive
  • 28:03 - 28:05
    threading support, and we've had it for the
    longest,
  • 28:05 - 28:07
    so it's just best if you test it on
  • 28:07 - 28:08
    JRuby to make sure.
  • 28:08 - 28:11
    T.E.: OK, I mentioned earlier that I wanted
    to
  • 28:11 - 28:15
    talk about improving embedding, especially
    since we're moving to
  • 28:15 - 28:19
    a new major version that's gonna break APIs.
  • 28:19 - 28:22
    First thing is, public is similar to public
    in
  • 28:22 - 28:25
    Ruby in that once something's marked public,
    anything can
  • 28:25 - 28:28
    call it. We have a huge code base and
  • 28:28 - 28:30
    we need to mark a bunch of things public.
  • 28:30 - 28:34
    Unfortunately, because it's public, then any
    native extension can
  • 28:34 - 28:36
    call it as well.
  • 28:36 - 28:38
    And I don't blame people for doing it. They're
  • 28:38 - 28:41
    calling these methods cause they have to.
    And they
  • 28:41 - 28:44
    probably represent gaps in our embedding API.
    But we
  • 28:44 - 28:47
    need to actually signal our intent that we
    think
  • 28:47 - 28:51
    that these are blessed APIs you can use, versus
  • 28:51 - 28:52
    we don't want you to use them.
  • 28:52 - 28:55
    So we're gonna also provide a tool, and let's
  • 28:55 - 28:57
    look at the solution - or part of the
  • 28:57 - 28:57
    solution.
  • 28:57 - 29:00
    C.N.: This is actually a problem that MRI
    is
  • 29:00 - 29:03
    faced with the C extension API. Without hiding
    some
  • 29:03 - 29:05
    of it, everything becomes the public API,
    and that's
  • 29:05 - 29:09
    a big reason why C extensions are hard or
  • 29:09 - 29:10
    impossible to support other implementations.
  • 29:10 - 29:12
    T.E.: Well, C doesn't have visibility at all,
    so
  • 29:12 - 29:14
    we get a little bit more protection, but not,
  • 29:14 - 29:17
    not a lot. So I'm not gonna teach people
  • 29:17 - 29:19
    how to go and write annotations in Java. This
  • 29:19 - 29:24
    is RubyConf. But this is really great. I'm
    just
  • 29:24 - 29:26
    gonna talk about annotations a little bit.
  • 29:26 - 29:29
    This is metadata that you can attach to first
  • 29:29 - 29:33
    class concepts in the language. So in this
    case
  • 29:33 - 29:36
    we're creating an annotation called extension
    that we can
  • 29:36 - 29:39
    attach to methods. So we'll just put, add
    extension
  • 29:39 - 29:45
    in front of our method declaration and, and
    then
  • 29:45 - 29:49
    we specify that it has a runtime binding,
    which
  • 29:49 - 29:52
    means in your live-running Java program you
    could actually
  • 29:52 - 29:55
    ask that Java method at runtime, are you an
  • 29:55 - 29:55
    extension method?
  • 29:55 - 30:00
    So this metadata concept is, is really cool.
    In
  • 30:00 - 30:03
    usage, in our source we'll just mark the methods
  • 30:03 - 30:07
    that we have as extensions. And then, in our
  • 30:07 - 30:11
    native extensions we can use those and then
    run
  • 30:11 - 30:15
    a tool. We haven't actually wrote the tool,
    but
  • 30:15 - 30:18
    it'll be integrated into JRuby lint. It'll
    examine your
  • 30:18 - 30:20
    jar and it'll give you a report of things
  • 30:20 - 30:24
    that you are using that aren't blessed.
  • 30:24 - 30:26
    C.N.: Right. This is part of the transition.
    We
  • 30:26 - 30:27
    know we're gonna break some of those external
    APIs,
  • 30:27 - 30:29
    but we know the ones we're going to bless
  • 30:29 - 30:33
    as official, and can give reports to any library
  • 30:33 - 30:36
    that's out there using the bad APIs, what
    they're
  • 30:36 - 30:38
    using now and what they need to change to.
  • 30:38 - 30:40
    T.E.: We kind of get a double benefit as
  • 30:40 - 30:43
    well, because we can actually write a documentation
    generator
  • 30:43 - 30:46
    and we can actually generate an embedding
    document from
  • 30:46 - 30:48
    these annotations.
  • 30:48 - 30:49
    And the reason why I spent a little extra
  • 30:49 - 30:52
    time on this was because, wouldn't it be really
  • 30:52 - 30:54
    great if in Ruby 3 we actually added a
  • 30:54 - 30:57
    metadata facility so that we could go and
    attach
  • 30:57 - 30:59
    stuff to methods? There's just so many uses
    for
  • 30:59 - 31:03
    this, it'd be really nice to consider adding
    something
  • 31:03 - 31:06
    similar to Java annotations.
  • 31:06 - 31:09
    We're gonna go and cover some projects associated
    with
  • 31:09 - 31:13
    Google Summer of Code. JRuby actually had
    its own
  • 31:13 - 31:18
    organization for this and, well, examples
    are probably the
  • 31:18 - 31:19
    best way to show.
  • 31:19 - 31:21
    C.N.: We're, we have some Google Summer of
    Code
  • 31:21 - 31:23
    people here. There's one in front - OK. I
  • 31:23 - 31:25
    think some of the other ones that might, there's,
  • 31:25 - 31:27
    there's one other that's here, I think. I
    haven't
  • 31:27 - 31:29
    seen him around yet but, we had about, we
  • 31:29 - 31:31
    had ten people this year. How many did we
  • 31:31 - 31:31
    have last year?
  • 31:31 - 31:33
    T.E.: It was more.
  • 31:33 - 31:34
    C.N.: It was more, I think it was like-
  • 31:34 - 31:35
    T.E.: It was like fourteen.
  • 31:35 - 31:37
    C.N.: Thirteen? Thirteen students last year.
    Ten students this
  • 31:37 - 31:40
    year. So we're really trying to help get more
  • 31:40 - 31:44
    students into JRuby and into Ruby in general.
  • 31:44 - 31:48
    T.E.: The first one is actually from last
    year.
  • 31:48 - 31:50
    But it kind of fits into the talk about
  • 31:50 - 31:54
    opt IR. We realized we had a problem with
  • 31:54 - 31:58
    IR, and we sort of still have that problem.
  • 31:58 - 32:04
    This diagram totally shows it. We're doing
    more work.
  • 32:04 - 32:06
    If you think about JRuby, the one thing that
  • 32:06 - 32:08
    we're known for that we don't want to be
  • 32:08 - 32:10
    known for is our startup time.
  • 32:10 - 32:11
    C.N.: It sucks.
  • 32:11 - 32:14
    T.E.: So our startup time's getting-
  • 32:14 - 32:14
    C.N.: Want a little more overhead?
  • 32:14 - 32:17
    T.E.: Yeah. Let's add more overhead.
  • 32:17 - 32:20
    But we realized this, in, well before 2012,
    and
  • 32:20 - 32:24
    we had Aliaksei make a, work on a persistence
  • 32:24 - 32:28
    project, basically similar to just a compiler.
    You just
  • 32:28 - 32:30
    save your persistent data and then you read
    it
  • 32:30 - 32:33
    in, instead of having to recompile.
  • 32:33 - 32:38
    So, if the file's up-to-date, and it's been
    saved,
  • 32:38 - 32:41
    you just read that and save having to compile.
  • 32:41 - 32:44
    And ultimately, we have a break-even point.
    We have
  • 32:44 - 32:46
    to build and read that off a disk faster
  • 32:46 - 32:48
    than we can compile. And this is kind of
  • 32:48 - 32:50
    a lie. We actually have to be faster than
  • 32:50 - 32:54
    1.7 today, or people are gonna go, why did
  • 32:54 - 32:59
    you slow JRuby down even more for startup?
  • 32:59 - 33:02
    Unfortunately for this project, it ended up
    taking longer
  • 33:02 - 33:04
    to read the data in than it took to
  • 33:04 - 33:08
    actually compile it. But it basically boiled
    down to,
  • 33:08 - 33:11
    we were saving way too much data. Size really
  • 33:11 - 33:14
    does matter for, for read speed.
  • 33:14 - 33:17
    Also, we realized that a majority of the stuff
  • 33:17 - 33:19
    that we were actually reading in, we never
    actually
  • 33:19 - 33:24
    used. So we want to be more lazy. I'm
  • 33:24 - 33:28
    not gonna talk about interning. I was, but
    we'll
  • 33:28 - 33:29
    cut down.
  • 33:29 - 33:33
    So we're gonna use a binary format. And the
  • 33:33 - 33:36
    most important part is that we're gonna do
    incrementally
  • 33:36 - 33:39
    loading to be lazy, and this diagram will
    show
  • 33:39 - 33:42
    you why. If you look at all the basic
  • 33:42 - 33:45
    operations you would do on a day-to-day basis,
    you'll
  • 33:45 - 33:48
    notice this really strange ratio. It's an
    eighty-twenty ratio.
  • 33:48 - 33:51
    Eighty percent of the code that you actually
    load
  • 33:51 - 33:54
    when you startup, each of these activities
    is never
  • 33:54 - 33:58
    actually called. Now maybe for a longer running
    application
  • 33:58 - 34:01
    it does get called. But it seems like for
  • 34:01 - 34:05
    startup and, and common activities, the eighty-twenty
    rule applies.
  • 34:05 - 34:06
    Which is really, really weird.
  • 34:06 - 34:09
    C.N.: Yeah, it's weird that that ratio applied
    almost
  • 34:09 - 34:10
    across the board.
  • 34:10 - 34:12
    T.E.: So if we define the methods but we
  • 34:12 - 34:14
    don't actually parse any of the bodies, then
    we're
  • 34:14 - 34:19
    obviously going to be doing a lot less parsing.
  • 34:19 - 34:26
    RSense was updated. Eric West is here. Stand
    up
  • 34:26 - 34:33
    quick. I have to embarrass him a little bit.
  • 34:36 - 34:41
    If you haven't seen RSense, it's a library
    that
  • 34:41 - 34:44
    you can go and install, and put in to
  • 34:44 - 34:48
    your editors, like VI or eMacs, and it can
  • 34:48 - 34:52
    do simple things like code completion. But
    it actually
  • 34:52 - 34:56
    makes smart choices, because it actually is
    a full-type
  • 34:56 - 34:59
    inference engine.
  • 34:59 - 35:01
    In this case, this is a pretty simple form
  • 35:01 - 35:04
    of type inference, but it can figure out a
  • 35:04 - 35:09
    surprising amount of stuff. So it, it's something
    worth
  • 35:09 - 35:12
    looking into. But before I talk about how
    to
  • 35:12 - 35:17
    do that, let's describe the project.
  • 35:17 - 35:19
    The person who originally wrote it, wrote
    against JRuby,
  • 35:19 - 35:23
    and he wrote it against JRuby 1 point 3.
  • 35:23 - 35:25
    At some point after JRuby 1 point 3, we
  • 35:25 - 35:27
    ripped a bunch of stuff that he needed out
  • 35:27 - 35:30
    of it and put it into its own library,
  • 35:30 - 35:33
    and then, like all great opensource projects,
    it went
  • 35:33 - 35:36
    into decay.
  • 35:36 - 35:38
    But one of the downsides is you could still
  • 35:38 - 35:41
    use it today, but it would only support 1.8
  • 35:41 - 35:43
    syntax, which is a problem. And so Eric wanted
  • 35:43 - 35:44
    to fix that.
  • 35:44 - 35:47
    A second goal we had was that, if there
  • 35:47 - 35:52
    was any really interesting functionality that
    was in, our
  • 35:52 - 35:54
    sense that would be useful for the JRuby parser
  • 35:54 - 35:57
    project itself, that he would go in and move
  • 35:57 - 36:02
    that in. Or implement it differently, but
    move it
  • 36:02 - 36:03
    in.
  • 36:03 - 36:06
    So he did that. And it's good to go
  • 36:06 - 36:09
    except RSense hasn't been released. So we
    have to
  • 36:09 - 36:12
    talk to Matzuyama's son and figure out how
    to
  • 36:12 - 36:15
    get this released as a new gem.
  • 36:15 - 36:20
    Eric added this really cool tree differencing
    support, so
  • 36:20 - 36:23
    you can compare two different sub-trees and
    do all
  • 36:23 - 36:26
    sorts of things with it. And one thing that
  • 36:26 - 36:28
    he did with it concretely is he made a
  • 36:28 - 36:32
    gem called smart_diff, so if you go and take
  • 36:32 - 36:37
    a diff between two files, you'll get an HTML
  • 36:37 - 36:40
    file that looks like this. YOu'll see the
    blue
  • 36:40 - 36:43
    and grey highlighting back and forth.
  • 36:43 - 36:46
    Smart_diff is actually able to tell that I
    just
  • 36:46 - 36:50
    switched the order of these two files. And
    then
  • 36:50 - 36:52
    you would see the typical green and red output
  • 36:52 - 36:56
    for things that are added or deleted. It's,
    it's,
  • 36:56 - 36:57
    it's pretty cool.
  • 36:57 - 37:00
    So you can, you can use this just gem
  • 37:00 - 37:01
    install.
  • 37:01 - 37:03
    C.N.: It's just built on top of RSense. It
  • 37:03 - 37:04
    was a lot, obviously a lot more stuff we
  • 37:04 - 37:05
    could do with this.
  • 37:05 - 37:07
    T.E.: Oh, this is actually just built on JRuby
  • 37:07 - 37:08
    parser.
  • 37:08 - 37:12
    C.N.: Oh it's just built on the parser.
  • 37:12 - 37:12
    T.E.: Yeah.
  • 37:12 - 37:18
    jruby_visualizer is by Maximilian Konzack.
    He's not here today.
  • 37:18 - 37:22
    We need to have better tools to go and
  • 37:22 - 37:24
    analyze stuff at the IR level. We have a
  • 37:24 - 37:30
    lot of compiler passes running and, in particular,
    eventually
  • 37:30 - 37:32
    we want to get this tool to the point
  • 37:32 - 37:35
    where you can go and run your application
    and
  • 37:35 - 37:38
    it'll generate an event stream. You can save
    that
  • 37:38 - 37:40
    event stream, give it to us, and we can
  • 37:40 - 37:42
    look at all the changes that are happening
    in
  • 37:42 - 37:43
    the IR and figure out what went wrong.
  • 37:43 - 37:45
    C.N.: Right. See why it's not optimizing what
    it
  • 37:45 - 37:46
    should be.
  • 37:46 - 37:49
    T.E.: It's a GUI based application. It's certainly
    written
  • 37:49 - 37:52
    on top of the JRubyFX gem, which is something
  • 37:52 - 37:57
    that, myself, Eric, and Max, worked along
    with mostly
  • 37:57 - 37:58
    byte IT 101.
  • 37:58 - 38:01
    I don't, I can't pronounce his last name,
    so
  • 38:01 - 38:04
    I'm just gonna use his handle. But it's an
  • 38:04 - 38:08
    awesome GUI toolkit on JRubyFX. Use it.
  • 38:08 - 38:12
    OK. So here's just a couple of screen shots.
  • 38:12 - 38:14
    If you go and click on the AST in
  • 38:14 - 38:17
    the left, it'll just scroll to wherever on
    the
  • 38:17 - 38:20
    right and show you what code that is. So
  • 38:20 - 38:23
    there's a little bit of trace ability introduced.
    At
  • 38:23 - 38:25
    any point - I don't expect you to read
  • 38:25 - 38:28
    that - but it's more IR output. Actually that's
  • 38:28 - 38:33
    bigger than I thought.
  • 38:33 - 38:36
    It'll actually ask for the compiler passes
    executed, and
  • 38:36 - 38:39
    you can step through those and then pop up
  • 38:39 - 38:42
    the IR view to see what's changed. We actually
  • 38:42 - 38:45
    want this to be a more smart diff format
  • 38:45 - 38:48
    to actually get better information how it's
    changed, but
  • 38:48 - 38:50
    it's a Google Summer of Code project. A guy
  • 38:50 - 38:53
    can only do so much.
  • 38:53 - 38:55
    And lastly you can go and look through the
  • 38:55 - 38:57
    control flow graph. And we want to go in
  • 38:57 - 39:01
    and add more windows for more stuff. So.
  • 39:01 - 39:02
    MK.
  • 39:02 - 39:06
    C.N.: Another project we had this summer,
    Chamila worked
  • 39:06 - 39:09
    on DTrace Support for us. So Ruby 2 point
  • 39:09 - 39:12
    1 added DTrace probes. I think that was, Erin
  • 39:12 - 39:15
    Patterson added that.
  • 39:15 - 39:17
    We wanted to add the same thing, and Chamila
  • 39:17 - 39:19
    came along and decided that that was the project
  • 39:19 - 39:20
    that he'd like to do for Google Summer of
  • 39:20 - 39:24
    Code. It turns out OpenJDK does have DTrace
    support
  • 39:24 - 39:26
    in it, so we could just build on top
  • 39:26 - 39:29
    of those existing APIs.
  • 39:29 - 39:31
    Now what we have right now, it's about 90%
  • 39:31 - 39:34
    complete. And it passes a lot of MRIs tests
  • 39:34 - 39:37
    for the, the functionality that we've implemented.
    But the
  • 39:37 - 39:40
    thing we found out during the process is that,
  • 39:40 - 39:43
    unfortunately the DTrace support in OpenJDK
    only exists on
  • 39:43 - 39:44
    Solaris right now.
  • 39:44 - 39:48
    So, we're looking at other options, pulling
    the DTrace
  • 39:48 - 39:50
    support over to the BSDs, like OS ten where
  • 39:50 - 39:53
    we have DTrace. Pulling over the same APIs
    where
  • 39:53 - 39:57
    we have Linux equivalents of DTrace. Or possible
    calling
  • 39:57 - 39:59
    out to a, an external library.
  • 39:59 - 40:01
    But we do have the code available. We're gonna
  • 40:01 - 40:03
    try to get it merged in at least for
  • 40:03 - 40:04
    the Solaris platforms and see what we can
    do
  • 40:04 - 40:06
    for others.
  • 40:06 - 40:11
    Shoes. Shoes4 was another project that came
    along this
  • 40:11 - 40:13
    summer. We've also did some work last summer
    too,
  • 40:13 - 40:17
    Tobias worked on this one. So Shoes is basically
  • 40:17 - 40:20
    why the lucky stiff's GUI environment. It's
    very clean,
  • 40:20 - 40:22
    very simple to use. He wanted to come up
  • 40:22 - 40:25
    with something that would be really trivial
    and fun
  • 40:25 - 40:28
    to build complex GUI applications with.
  • 40:28 - 40:31
    Shoes4 actually made the decision, last year
    some time
  • 40:31 - 40:34
    I think, to move to a JRuby-only backend.
    There's
  • 40:34 - 40:37
    a lot of reasons for this. Most of them,
  • 40:37 - 40:39
    portability, not having to build the libraries
    over and
  • 40:39 - 40:42
    over again, and having a consistent experience
    across all
  • 40:42 - 40:46
    platforms. Building it on top of GTK or Win32
  • 40:46 - 40:50
    or whatever else never worked great across
    platforms. Things
  • 40:50 - 40:52
    always developed a little bit different and
    it was
  • 40:52 - 40:55
    very difficult to ship applications, since
    everybody needed to
  • 40:55 - 40:57
    install those extra libraries and build them
    for that
  • 40:57 - 40:59
    platform.
  • 40:59 - 41:02
    In the other room, in one of the salons,
  • 41:02 - 41:06
    there's actually a talk on an application
    that uses
  • 41:06 - 41:10
    DRb and Shoes4 to do a Space Team-like pirate
  • 41:10 - 41:15
    game. And that's Davy, Eric, and Ryan are
    talking
  • 41:15 - 41:16
    about that in the other room. And since they
  • 41:16 - 41:19
    couldn't be here and we couldn't be there,
    I
  • 41:19 - 41:21
    thought we'd get a video from them to show
  • 41:21 - 41:22
    this application running.
  • 41:22 - 41:25
    And so this is just all, this is written
  • 41:25 - 41:27
    all in Ruby code, using Shoes, which is backed
  • 41:27 - 41:32
    by SWT, one of the JVM GUI libraries. Anybody
  • 41:32 - 41:35
    play - any Space Team players here? Not too
  • 41:35 - 41:35
    many.
  • 41:35 - 41:37
    The goal, basically, is you have two or three
  • 41:37 - 41:41
    or four people, and it shouts out commands
    to
  • 41:41 - 41:43
    you, and you have to do them quickly. Or
  • 41:43 - 41:45
    yell it out to your friends so that they'll
  • 41:45 - 41:46
    do the commands.
  • 41:46 - 41:49
    So, there you go. So that was, that's fun,
  • 41:49 - 41:51
    and it's cool that, that it's actually being
    used
  • 41:51 - 41:52
    now.
  • 41:52 - 41:55
    Some more Google Summer of Code stuff we don't
  • 41:55 - 41:57
    have time to cover - more work on Ruboto,
  • 41:57 - 42:00
    which is JRuby on Android, trying to strip
    down
  • 42:00 - 42:03
    the runtime, improve performance, make it
    easier to build
  • 42:03 - 42:08
    Android applications entirely in Ruby. Asakawa
    Ryu did that.
  • 42:08 - 42:12
    Shoes4 HacketyHack support. Faraaz did that.
    We don't, we
  • 42:12 - 42:15
    mostly let the Shoes guy mentor that, so we
  • 42:15 - 42:16
    didn't track that very much.
  • 42:16 - 42:18
    For the second year in a row we had
  • 42:18 - 42:20
    two students working on Krypt. Krypt is a
    new
  • 42:20 - 42:27
    encryption, encoding library for Ruby, intended
    to, hopefully, replace
  • 42:28 - 42:32
    OpenSSL at some point. But, implemented in
    Ruby, where
  • 42:32 - 42:35
    it can be native where possible, and supporting
    all
  • 42:35 - 42:37
    the implementations at the same time. So we've
    always
  • 42:37 - 42:40
    got a good solid encryption library.
  • 42:40 - 42:41
    And we're very happy that we're able to support
  • 42:41 - 42:43
    that every year in Google Summer of Code.
  • 42:43 - 42:45
    And we also had a student explore JRuby on
  • 42:45 - 42:48
    embedded devices like raspberry pies and stuff
    like that.
  • 42:48 - 42:51
    He basically came up with a bunch of different
  • 42:51 - 42:54
    matrices of which libraries, which JRuby,
    which JRuby versions
  • 42:54 - 42:58
    work on which platforms with which embedded
    JVMs. And
  • 42:58 - 43:01
    we've got all that information available on,
    in the
  • 43:01 - 43:04
    JRuby organization on GitHub.
  • 43:04 - 43:07
    So. Wrapping things up. Emphasizing that JRuby
    is just
  • 43:07 - 43:09
    Ruby - it just happens to be on the
  • 43:09 - 43:12
    JVM. We're working with the MRI and the community
  • 43:12 - 43:15
    a lot more, more and more in the future.
  • 43:15 - 43:17
    If anybody has gems or libraries you're releasing,
    please,
  • 43:17 - 43:21
    please turn on JRuby and Travis. If it's not
  • 43:21 - 43:22
    passing, let us know and we'll help you figure
  • 43:22 - 43:24
    out why.
  • 43:24 - 43:26
    And, you know, if you're not trying JRuby
    right
  • 43:26 - 43:28
    now, give it a shot. Let us know how
  • 43:28 - 43:30
    it goes for you and let us know what
  • 43:30 - 43:32
    we can improve. So thanks.
Title:
Ruby Conf 2013 - The Future of JRuby by Charles Nutter and Thomas Enebo
Description:

more » « less
Duration:
44:01

English subtitles

Revisions