Skip to main content
Why JRuby?
Me

• Charles Oliver Nutter
 • @headius
• Java developer since 1996
• JRuby developer since 2006
• Red Hat / JBoss polyglot group
What is JRuby?
Ruby on JVM
• Core classes and runtime in Java
 • Moving parts to Ruby over time
• Standard command line
• 1.8 and 1.9 compatible
 • 1.9 default in JRuby 1.7
• Drop in replacement for MRI*
*caveats

• Weak but improving low-level UNIX stuff
• No C extension support
 • Not maintained...off by default in 1.7
• Some features differ or unavailable
 • ObjectSpace, trace funcs, callcc, fork...
JRuby 1.7

• Ruby 1.9.3 mode by default
 • Many 1.9 compat fixes
• Numerous perf improvements
 • Java 7 invokedynamic support
• Beginning of new optimizing compiler
Getting Started

• Need a JVM...
• rvm install jruby
 • rvm install jruby-1.7.0-RC1
• Download manually
 • Unpack, edit PATH, done
Try it Out
def fractal_flipflop
  w, h = 44, 54
  c = 7 + 42 * w
  a = [0] * w * h
  g = d = 0
  f = proc do |n|
    a[c] += 1
    o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/)
    puts "f" + o.map {|l| l.rstrip }.join("n")
    d += 1 - 2 * ((g ^= 1 << n) >> n)
    c += [1, w, -1, -w][d %= 4]
  end
  1024.times do
    !!(!!(!!(!!(!!(!!(!!(!!(!!(true...
     f[0])...f[1])...f[2])...
     f[3])...f[4])...f[5])...
     f[6])...f[7])...f[8])
  end
end
def fractal_flipflop
  w, h = 44, 54
  c = 7 + 42 * w
  a = [0] * w * h
  g = d = 0
  f = proc do |n|
    a[c] += 1
    o = a.map {|z| " :#"[z, 1] * 2 }.join.scan(/.{#{w * 2}}/)
    puts "f" + o.map {|l| l.rstrip }.join("n")
    d += 1 - 2 * ((g ^= 1 << n) >> n)
    c += [1, w, -1, -w][d %= 4]
  end
  1024.times do
    !!(!!(!!(!!(!!(!!(!!(!!(!!(true...
     f[0])...f[1])...f[2])...
     f[3])...f[4])...f[5])...
     f[6])...f[7])...f[8])
  end
end
JRuby is the best*
  Ruby runtime
The Team
JRuby Team
JRuby Team


    Charlie
JRuby Team

               Charlie                  Tom




Nick   Hiro   Marcin     Nahi   Wayne   Subbu   Douglas   Douglas
                                                           Douglas
                                                           Contribs
JRuby Team

                Charlie                          Tom




Nick   Hiro    Marcin        Nahi     Wayne      Subbu    Douglas   Douglas
                                                                     Douglas
                                                                     Contribs




          Douglas
           Douglas        Douglas
                           Douglas    Douglas
                                       Douglas       Douglas
                                                       Other
                                                      Douglas
           OpenJDK          Android       J9
                                                         JVMs
JRuby Structure
                 JRuby
          Bytecode    Core       Java
Parser
             JIT     Classes    Integ

                 JVM
                       Native
Threads     GC                  C API
                        JIT
JRuby Structure
                   JRuby
             Bytecode    Core      Java
    Parser
                JIT     Classes   Integ


JRuby team can focus on implementing JRuby.
JRuby Team Doesn’t
     Have to Work On*
•   Memory allocation     •   Native JIT

•   Garbage collectors    •   Tooling

•   Native threading      •   Server environments

•   Cross-platform        •   Native extensions

•   Mobile/Embedded VMs
We could stop working
on JRuby and it would
continue to get faster.
Platforms
Systems

• Best Ruby on Windows?
• Exotic platforms: zLinux, OpenVMS, AS/400
• Android’s Dalvik
• Embedded JVMs
actionmailer-javamail, active_documentum, activerecord-jdbc-adapter, activerecord-jdbcdbf-adapter, activerecord-jdbcderby-adapter, activerecord-jdbch2-
adapter, activerecord-jdbchsqldb-adapter, activerecord-jdbcmssql-adapter, activerecord-jdbcmysql-adapter, activerecord-jdbcpostgresql-adapter, activerecord-
    jdbcsqlite3-adapter, activerecord-netezza-adapter, activerecord-vertica-adapter, akephalos, akephalos-nerian, akephalos2, akka-actor-jars, akka-remote-jars,
    akubra_llstore_migrate, Antwrap, async-http-client-jars, atomic, atoulme-Antwrap, autotest-java, bbrowning-deltacloud-client, bbrowning-deltacloud-core,
   bcrypt-ruby, bee_java, berkeley-db-java-jars, bert, bio-maf, blockenspiel, boc, bond, bosdk, bouncy-castle-java, boxed-geminabox, brute-fuzzy, bryanl-gherkin,
 bson, buby, buildr, buildr-resolver, buildrizpack, butternut, capistrano-java, capybara-java_script_lint, carrierwave-neo4j, carrierwave_imagevoodoo, cassandra-
   jars, chrest, cloby, commons-io-jars, concurrently, contextual, coupler, cucumber-java, cucumber-jvm, cuke4duke, cuuid, dm-ldap-adapter, dm-lucene-adapter,
  do-jdbc_sqlserver, do_derby, do_h2, do_hsqldb, do_jdbc, do_mysql, do_openedge, do_oracle, do_postgres, do_sqlite3, do_sqlserver, doubleshot, dripdrop,
    dubious, duby, engineyard-visualvm, epall-limelight, errbit_zmq_handler, eurydice, euston, euston-daemons, euston-eventstore, euston-projections, euston-
   rabbitmq, euston-websites, eventmachine, excemel, faye-websocket, ffi, fig, file-find, fishwife, foreman, forkit, forkjoin, gamelan, gemshit, geoip-jars, get_back,
 gherkin, glassfish, gravitext-util, gravitext-xmlprod, grizzly, guava-jars, hadoop-find, hashdot-test-daemon, hiredis, hitimes, hope, hostor, hot_bunnies, hourglass,
 hpricot, http_parser.rb, inline_javascript, iudex, iudex-async-httpclient, iudex-barc, iudex-brutefuzzy-protobuf, iudex-brutefuzzy-service, iudex-char-detector,
 iudex-core, iudex-da, iudex-filter, iudex-html, iudex-http, iudex-http-test, iudex-httpclient-3, iudex-jetty-httpclient, iudex-rome, iudex-simhash, iudex-worker,
            ivy-jars, iyyov, jactive_support, java-autotest, java-inline, java2ruby-xmldsig, java_bin, java_inline, java_override, java_properties, java_streamify,
java_testing_guff, javabean_xml, javaclass, javaeye4r, javagems, javajake, javaobj, javaobjs, javaobs, javaparse, javasand, javascript-securehash-rails, javascript-state-
                machine-rails, javascript_auto_include, javascript_eraser, javascript_features, javascript_i18n, javascript_localize, javascript_safe_logger,
  javascript_util_asset_pack, javascripto, javascripto-rails, jdbc-derby, jdbc-hsqldb, jdbc-jtds, jdbc-openedge, jdbc-openedge-internal, jdbc-postgres, jdbc-sqlite3,
      jedis-jars, jena-jruby, jessica, jettr, jetty, jetty-jsp, jgeoip, jms4r, jpdfer, jrack_handlers, jrtm, jruby-activemq, jruby-akka_jars, jruby-elasticsearch_jars, jruby-
      httpclient, jruby-launcher, jruby-management, jruby-metrics, jruby-pageant, jruby-vijava, jruby_gc_stats, jruby_sandbox, jruby_threach, jrubyconf-button,
  jsmetric4java, json, json-jruby, jsound, kb-activerecord-jdbc-adapter, kirk, kyotocabinet-java, ladle, latex-decode, launchy, libnotify, limelight, linecache, logback,
       logback-jars, looksee, lumix, mack-javascript, markdownj, maven_irb_plugin, metrics-core-jars, metrics-java, mguymon-buildr, mikka, mini_aether, mirah,
mirah_model, miso-java, mixology, mm_mq, mongrel, msgpack-idl-java, msgpack-jruby, multimeter, naether, nanoc-javascript-concatenator, neo4j, neo4j-admin,
      neo4j-advanced, neo4j-community, neo4j-core, neo4j-enterprise, neo4j-spatial, neo4j-will_paginate, neo4j-wrapper, netty-jars, ning-compress-jars, nio4r,
nokogiri, nokogiri-fitzsimmons, nokogiri-maven, nosqoop4u, ontomde-demo-java5, ontomde-java, ontomde-java-frontend, ontomde-uml2-java, ontomde-uml2-
               kbjava, open_nlp, pacer, pacer-dex, pacer-neo4j, pacer-orient, pelops-jars, persvr, pg_array_parser, protobuf-jars, pry, puma, qtjruby-core,
      qwirk_active_mq_adapter, qwirk_jms_adapter, rabbitmqadmin-cli, ragweed, rails_javascript_helpers, rakejava, rave, rcov, realityforge-jekyll, realityforge-
    jekylltask, redcar-bundles, redcar-clojure, redcar-filter-through-command, redcar-groovy, redcar-icons, redcar-javamateview, redcar-javascript, redcar-mirah,
        redcar-svnkit, redcar-xulrunner-win, RedCloth, refinerycms-javascripts, reigns, revo-nokogiri, rika, rjack-async-httpclient, rjack-commons-codec, rjack-
commons-dbcp, rjack-commons-dbutils, rjack-commons-pool, rjack-httpclient-3, rjack-httpclient-4, rjack-icu, rjack-jackson, rjack-jdom, rjack-jets3t, rjack-jetty,
     rjack-jetty-jsp, rjack-jms, rjack-jms-spec, rjack-logback, rjack-lucene, rjack-maven, rjack-mina, rjack-nekohtml, rjack-protobuf, rjack-qpid-client, rjack-rome,
  rjack-slf4j, rjack-solr, rjack-tarpit, rjack-xerces, rmagick4j, rmodbus, rtm-javatmapi, rtm-majortom, rtm-ontopia, rtm-tinytim, rtm-tmql, rubeus, rubinius-core-
 api, ruby-blockcache, ruby-debug-base, ruby-maven, ruby2java, rubydoop, rubyjedi-nokogiri_java, scala-inline, scala-library-jars, scriptty, slf4j, slf4j-jars, slyphon-
     zookeeper, slyphon-zookeeper_jar, smackr, smartimage, SNMP4JR, solr_sail, spiegela-jruby-httpclient, sproutcore, spymemcached, sqldroid, steamcannon-
 deltacloud-client, steamcannon-deltacloud-core, stilts-stomp-client, supermarket, svm_toolkit, swt, theduke, thick, to-javascript, torquebox-base, torquebox-
    cache, torquebox-configure, torquebox-container-foundation, torquebox-core, torquebox-messaging, torquebox-messaging-container, torquebox-naming,
 torquebox-naming-container, torquebox-security, torquebox-server, torquebox-vfs, torquebox-web, twitter4j4r, UDJrb, unageanu-javaclass, unimidi, universe-
 javascript, url_escape, weakling, webbit-jars, wildnet-jackson, wildnet-netty, wildnet-server, wildsonet-hazelcast, wildsonet-netty, wildsonet-server, wildsonet-
                                                                   streamer, wrest, wrong, xdojava, xqruby, zookeeper
actionmailer-javamail, active_documentum, activerecord-jdbc-adapter, activerecord-jdbcdbf-adapter, activerecord-jdbcderby-adapter, activerecord-jdbch2-
adapter, activerecord-jdbchsqldb-adapter, activerecord-jdbcmssql-adapter, activerecord-jdbcmysql-adapter, activerecord-jdbcpostgresql-adapter, activerecord-
    jdbcsqlite3-adapter, activerecord-netezza-adapter, activerecord-vertica-adapter, akephalos, akephalos-nerian, akephalos2, akka-actor-jars, akka-remote-jars,
    akubra_llstore_migrate, Antwrap, async-http-client-jars, atomic, atoulme-Antwrap, autotest-java, bbrowning-deltacloud-client, bbrowning-deltacloud-core,
   bcrypt-ruby, bee_java, berkeley-db-java-jars, bert, bio-maf, blockenspiel, boc, bond, bosdk, bouncy-castle-java, boxed-geminabox, brute-fuzzy, bryanl-gherkin,
 bson, buby, buildr, buildr-resolver, buildrizpack, butternut, capistrano-java, capybara-java_script_lint, carrierwave-neo4j, carrierwave_imagevoodoo, cassandra-
   jars, chrest, cloby, commons-io-jars, concurrently, contextual, coupler, cucumber-java, cucumber-jvm, cuke4duke, cuuid, dm-ldap-adapter, dm-lucene-adapter,
  do-jdbc_sqlserver, do_derby, do_h2, do_hsqldb, do_jdbc, do_mysql, do_openedge, do_oracle, do_postgres, do_sqlite3, do_sqlserver, doubleshot, dripdrop,
    dubious, duby, engineyard-visualvm, epall-limelight, errbit_zmq_handler, eurydice, euston, euston-daemons, euston-eventstore, euston-projections, euston-
   rabbitmq, euston-websites, eventmachine, excemel, faye-websocket, ffi, fig, file-find, fishwife, foreman, forkit, forkjoin, gamelan, gemshit, geoip-jars, get_back,
 gherkin, glassfish, gravitext-util, gravitext-xmlprod, grizzly, guava-jars, hadoop-find, hashdot-test-daemon, hiredis, hitimes, hope, hostor, hot_bunnies, hourglass,
 hpricot, http_parser.rb, inline_javascript, iudex, iudex-async-httpclient, iudex-barc, iudex-brutefuzzy-protobuf, iudex-brutefuzzy-service, iudex-char-detector,
 iudex-core, iudex-da, iudex-filter, iudex-html, iudex-http, iudex-http-test, iudex-httpclient-3, iudex-jetty-httpclient, iudex-rome, iudex-simhash, iudex-worker,
            ivy-jars, iyyov, jactive_support, java-autotest, java-inline, java2ruby-xmldsig, java_bin, java_inline, java_override, java_properties, java_streamify,
java_testing_guff, javabean_xml, javaclass, javaeye4r, javagems, javajake, javaobj, javaobjs, javaobs, javaparse, javasand, javascript-securehash-rails, javascript-state-
                machine-rails, javascript_auto_include, javascript_eraser, javascript_features, javascript_i18n, javascript_localize, javascript_safe_logger,
  javascript_util_asset_pack, javascripto, javascripto-rails, jdbc-derby, jdbc-hsqldb, jdbc-jtds, jdbc-openedge, jdbc-openedge-internal, jdbc-postgres, jdbc-sqlite3,
      jedis-jars, jena-jruby, jessica, jettr, jetty, jetty-jsp, jgeoip, jms4r, jpdfer, jrack_handlers, jrtm, jruby-activemq, jruby-akka_jars, jruby-elasticsearch_jars, jruby-

                             No build tools, no native exts required!
      httpclient, jruby-launcher, jruby-management, jruby-metrics, jruby-pageant, jruby-vijava, jruby_gc_stats, jruby_sandbox, jruby_threach, jrubyconf-button,
  jsmetric4java, json, json-jruby, jsound, kb-activerecord-jdbc-adapter, kirk, kyotocabinet-java, ladle, latex-decode, launchy, libnotify, limelight, linecache, logback,
       logback-jars, looksee, lumix, mack-javascript, markdownj, maven_irb_plugin, metrics-core-jars, metrics-java, mguymon-buildr, mikka, mini_aether, mirah,
mirah_model, miso-java, mixology, mm_mq, mongrel, msgpack-idl-java, msgpack-jruby, multimeter, naether, nanoc-javascript-concatenator, neo4j, neo4j-admin,
      neo4j-advanced, neo4j-community, neo4j-core, neo4j-enterprise, neo4j-spatial, neo4j-will_paginate, neo4j-wrapper, netty-jars, ning-compress-jars, nio4r,
nokogiri, nokogiri-fitzsimmons, nokogiri-maven, nosqoop4u, ontomde-demo-java5, ontomde-java, ontomde-java-frontend, ontomde-uml2-java, ontomde-uml2-
               kbjava, open_nlp, pacer, pacer-dex, pacer-neo4j, pacer-orient, pelops-jars, persvr, pg_array_parser, protobuf-jars, pry, puma, qtjruby-core,
      qwirk_active_mq_adapter, qwirk_jms_adapter, rabbitmqadmin-cli, ragweed, rails_javascript_helpers, rakejava, rave, rcov, realityforge-jekyll, realityforge-
    jekylltask, redcar-bundles, redcar-clojure, redcar-filter-through-command, redcar-groovy, redcar-icons, redcar-javamateview, redcar-javascript, redcar-mirah,
        redcar-svnkit, redcar-xulrunner-win, RedCloth, refinerycms-javascripts, reigns, revo-nokogiri, rika, rjack-async-httpclient, rjack-commons-codec, rjack-
commons-dbcp, rjack-commons-dbutils, rjack-commons-pool, rjack-httpclient-3, rjack-httpclient-4, rjack-icu, rjack-jackson, rjack-jdom, rjack-jets3t, rjack-jetty,
     rjack-jetty-jsp, rjack-jms, rjack-jms-spec, rjack-logback, rjack-lucene, rjack-maven, rjack-mina, rjack-nekohtml, rjack-protobuf, rjack-qpid-client, rjack-rome,
  rjack-slf4j, rjack-solr, rjack-tarpit, rjack-xerces, rmagick4j, rmodbus, rtm-javatmapi, rtm-majortom, rtm-ontopia, rtm-tinytim, rtm-tmql, rubeus, rubinius-core-
 api, ruby-blockcache, ruby-debug-base, ruby-maven, ruby2java, rubydoop, rubyjedi-nokogiri_java, scala-inline, scala-library-jars, scriptty, slf4j, slf4j-jars, slyphon-
     zookeeper, slyphon-zookeeper_jar, smackr, smartimage, SNMP4JR, solr_sail, spiegela-jruby-httpclient, sproutcore, spymemcached, sqldroid, steamcannon-
 deltacloud-client, steamcannon-deltacloud-core, stilts-stomp-client, supermarket, svm_toolkit, swt, theduke, thick, to-javascript, torquebox-base, torquebox-
    cache, torquebox-configure, torquebox-container-foundation, torquebox-core, torquebox-messaging, torquebox-messaging-container, torquebox-naming,
 torquebox-naming-container, torquebox-security, torquebox-server, torquebox-vfs, torquebox-web, twitter4j4r, UDJrb, unageanu-javaclass, unimidi, universe-
 javascript, url_escape, weakling, webbit-jars, wildnet-jackson, wildnet-netty, wildnet-server, wildsonet-hazelcast, wildsonet-netty, wildsonet-server, wildsonet-
                                                                   streamer, wrest, wrong, xdojava, xqruby, zookeeper
Servers

• Any Java server can host Ruby
• Trinidad
 • Ruby-style CLI server atop Tomcat
• Torquebox
 • Full Ruby stack atop JBossAS
Ruby App
 Sinatra      Rails
       Rack
  Passenger/Thin


 Apache/Nginx
Ruby App
              Sinatra      Rails
                    Rack
   Tasks       Passenger/Thin
 Resque/
DelayedJob    Apache/Nginx
Ruby App
              Sinatra      Rails
                    Rack
   Tasks       Passenger/Thin      Jobs
 Resque/
DelayedJob    Apache/Nginx         crond
Ruby App
              Sinatra      Rails
                    Rack
   Tasks       Passenger/Thin      Jobs
 Resque/
DelayedJob    Apache/Nginx         crond


                 Daemons


                god/monit
TorqueBox AS
Sinatra      Rails
      Rack            Tasks   Procs            Jobs        Daemons
      Web               Messaging        Scheduling        Services

                                JBoss AS
               Clustering     Load Balancing          HA
Torquebox
•   Rack-compatible         •   Server management

•   Database connectivity   •   Clustering

•   Background daemons      •   In and out-process cache

•   Scheduled jobs          •   Web sockets

•   Messaging               •   Authentication

•   Asynchronous tasks      •   XA Transactions
Torquebox
•   Rack-compatible         •   Server management

•   Database connectivity   •   Clustering

•   All R
    Background daemons      •   In and out-process cache

•   Scheduled jobs
                      uby   •   Web sockets

•   Messaging
                          APIs
                            •   Authentication

•   Asynchronous tasks      • ! XA Transactions
Ruby-friendly Config
TorqueBox.configure do
  ruby do                ruby:
    version "1.9"          version: 1.9
    compile_mode "off"     compile_mode: off
    debug false            debug: false
    interactive true       interactive: true
    profile_api true       profile_api: true
  end
end
Messaging
                                 application:
TorqueBox.configure do             ..
  ...                            queues:
  queue '/queues/my_app_queue'     /queues/my_app_queue:
  topic '/queues/my_app_topic'
end                              topics:
                                   /queues/my_app_topic:
Messaging
queue = fetch('/queues/foo')
queue.publish "A text message"

topic = fetch('/topics/foo')
topic.publish "A text message"

queue = TorqueBox::Messaging::Queue.new('/queues/foo')
message = queue.receive

topic = TorqueBox::Messaging::Topic.new('/topics/foo')
message = topic.receive
Libraries
Libraries

• 340k versioned jars in Maven central
 • Compare to 35k gems in RubyGems.org
• Vast majority have no native code
• All usable from JRuby
JavaFX

• Scene graph + optimized graphics
• Normal Java library now
 • R.I.P. JavaFX Script
• jrubyfx, other projects to wrap it
    @minute_hand = Path.new.tap do |mh|
      mh.fill = Color::BLACK
      mh.elements << MoveTo.new(4, -4)
      mh.elements << ArcTo.new(-1, -1, 0, -4, -4, false, false)
      mh.elements << LineTo.new(0, -radius)
      mh.transforms << Rotate.new
    end
 
    @hour_hand = Path.new.tap do |hh|
      hh.fill = Color::BLACK
      hh.elements << MoveTo.new(4, -4)
      hh.elements << ArcTo.new(-1, -1, 0, -4, -4, false, false)
      hh.elements << LineTo.new(0, -radius/4*3)
      hh.transforms << Rotate.new
    end
Purugin

• Minecraft scripting in JRuby
• Clean and simple DSL
• Purogo: LOGO for Minecraft
turtle("four-sided triangle") do |*args|
  dim = (args[0] || 5).to_i
  block_type = (args[1] || :stone).to_sym

  layer do
    4.times do |i|
      forward dim
      turnleft 90
    end
  end
  
  pivot do
    block :none
    forward 1
    turnleft 90
    forward 1
    turnup 90
    forward 1
    turndown 90
    turnright 90
    block block_type
  end

  block block_type
  (1...dim).step(2).to_a.reverse.each do |i|
    dim = i
    layer
    pivot
  end
end
Threepence

• Ruby APIs atop Ardor3D library
 • Various games atop Ardor3D
• All-in-one clone from Github
 • Linux, OS X, Windows, Solaris provided
require 'example_base'

class Box < ExampleBase
  def initialize
    super("Box Example")
  end

  def init_application
    root.layout do
      cull_state :back
      skybox(:sky, 500, 500, 500, 'images/skybox/blue')
      node(:spinning) do
        behavior :rotating, Vector3(1, 1, 0.5), 50

        box(:left_box, 1, 1, 1) do
          behavior :rotating, Vector3(0.5, 1, 1), 50
          at 0, 0, -3
          texture "images/ardor3d_white_256.jpg"
        end.duplicate_as(:right_box) do
        at 0, 0, 3
" end
      end
    end
  end
end

Box.start
GC
GC Matters

• Applications grow over time
• Ruby is very object-heavy
• Multicore MRI multiplies the problem
• You will eventually have issues
JVM GC

• Wide array of options
• Many GCs to choose from
• Scales up to massive heaps
• Best GCs in the world!
OpenJDK GCs

• Parallel: multi-core stop-the-world
• Concurrent: STW young, concurrent old
• G1: concurrent young and old
• Serial: single-thread STW
gc_demo1.rb


• Heavy GC, mix of old and young
• Steadily growing heap use
class Simple
  attr_accessor :next
end

top = Simple.new

puts Benchmark.measure {
  outer = 10
  total = 100000
  per = 100

  outer.times do
    total.times do
      per.times { Simple.new }
      s = Simple.new
      top.next = s
      top = s
    end
  end
}
Ruby 1.9.3              JRuby
8000



6000



4000



2000



   0
                    GC count
Ruby 1.9.3              JRuby
10000



 1000



  100



   10



    1
                     GC count
15
        Ruby 1.9.3               JRuby



11.25




  7.5




 3.75




   0
                     GC time %
Ruby 2.0.0                      JRuby
                 Time per GC versus heap usage
300ms



225ms



150ms



75ms



 0ms
 188KB/29MB                  27MB/127MB               199MB/238MB
                     Heap usage (MRI/JRuby)
gc_demo2.rb


• Frequent GC, all young objects
• Steadily growing heap use
10.times do
  old_ary = []
  10000.times do
    old_ary << 'foo'
    new_ary = []
    100000.times do
      new_ary << 'bar'
    end
  end
  puts "looped"
end
Ruby 1.9.3                  JRuby

5000



3750



2500



1250



   0
                    GC time (ms)
JRuby (Concurrent)                  Ruby 2.0.0
                                  World-stopping GC pause times
               0.3s



             0.225s
Pause time




              0.15s



             0.075s



                0s
                      0       5                10                 15       20
                                       Seconds since start
JRuby (Concurrent)                  Ruby 2.0.0
                                  World-stopping GC pause times
               0.3s


                                                                  im es
             0.225s
                                                         useT
                                                       Pa
Pause time




              0.15s



             0.075s



                0s
                      0       5                10                 15       20
                                       Seconds since start
JRuby (Concurrent)                   Ruby 2.0.0
                                  World-stopping GC pause times
               0.3s


                                                                  im es
             0.225s
                                                         useT
                                                       Pa
Pause time




              0.15s
                                                    Use
                                                        r    Ha
                                                               ppi
             0.075s                                                  nes
                                                                        s :-
                                                                               (
                0s
                      0       5                10                 15               20
                                       Seconds since start
Findings

• Lower, more uniform individual GC time
• Lower overall GC time
• Lower application pause times
• More predictable, consistent apps
Threads
Real Parallellism

• Ruby thread = JVM thread = native thread
• One process can use all cores
• One server can handle all requests
require 'benchmark'

ary = (1..1000000).to_a

loop {
  puts Benchmark.measure {
    10.times {
      ary.each {|i|}
    }
  }
}
require 'benchmark'

ary = (1..1000000).to_a

loop {
  puts Benchmark.measure {
    (1..10).map {
      Thread.new {
        ary.each {|i|}
      }
    }.map(&:join)
  }
}
Ruby 1.9
unthreaded
Ruby 1.9    Ruby 1.9
unthreaded   threaded
Ruby 1.9    Ruby 1.9
unthreaded   threaded




  JRuby
unthreaded
Ruby 1.9    Ruby 1.9
unthreaded   threaded




  JRuby        JRuby
unthreaded   threaded
threaded_reverse
                     Per-iteration time versus thread count
 0.8s



0.65s



 0.5s



0.35s



 0.2s
        one thread      two threads        three threads      four threads
Nonlinear?

• More work means more objects
• More objects needs memory bandwidth
• No different from multi-process
Tools
Profiling

• Java profilers
 • VisualVM,YourKit, NetBeans, JXInsight
• jruby [--profile | --profile.graph]
• jruby -Xreify.classes=true
• JVM command-line profilers
Monitoring

• Java Management Extensions (JMX)
 • Gems available for clients and servers
• jconsole and VisualVM
• Most servers provide additional tools
• New Relic, etc have JVM support
VisualVM

• CPU, memory, thread monitoring
• CPU and memory profiling
• VisualGC
• Heap analysis
Performance
Performance

• JRuby compiles Ruby to JVM bytecode
• JVM compiles bytecode to native
• Best JIT technology in the world
• Getting even better with invokedynamic
def foo
  bar
end

def bar
  baz     foo   bar   baz
end

def baz
  # ...
end
JRuby on Java 5/6
def foo
  bar
end

def bar            JRuby            JRuby
  baz     foo        call   bar       call     baz
end                 logic            logic
def baz
  # ...
end
                Kills many JVM optimizations
JRuby on Java 7
def foo
  bar




                   X X
end

def bar             JRuby             JRuby
  baz     foo         call    bar       call   baz
end                  logic             logic
def baz
  # ...
end
                Dynamic call logic built into JVM
JRuby on Java 7
def foo
  bar
end

def bar
  baz     foo               bar              baz
end

def baz
  # ...
end
                Straight through dispatch path
JRuby on Java 7
def foo
  bar
end

def bar
  baz           foo       bar       baz
end

def baz
  # ...
end
          Optimizations (like inlining) can happen!
def foo; 1; end
        def invoker; foo; end
        i = 0
        while i < 10000
          invoker
          i+=1
        end
  0x00000001060a1be0:   mov      %eax,-0x14000(%rsp)
  0x00000001060a1be7:   push     %rbp
  0x00000001060a1be8:   sub      $0x30,%rsp
  0x00000001060a1bec:   mov      0x8(%rcx),%r10d
  0x00000001060a1bf0:   cmp      $0xfb7aedc9,%r10d
  0x00000001060a1bf7:   jne      0x00000001060a1c39
  0x00000001060a1bf9:   mov      %rcx,%r10
  0x00000001060a1bfc:   mov      0x10(%r10),%ebp
  0x00000001060a1c00:   cmp      $0xfed77602,%ebp
  0x00000001060a1c06:   jne      0x00000001060a1c1e
  0x00000001060a1c08:   movabs   $0x7f6bf4bb0,%rax
  0x00000001060a1c12:   add      $0x30,%rsp
  0x00000001060a1c16:   pop      %rbp
  0x00000001060a1c17:   test     %eax,-0xec3c1d(%rip)
  0x00000001060a1c1d:   retq
def invoker; 1; end
        i = 0
        while i < 10000
          invoker
          i+=1
        end
  0x00000001060a1be0:   mov      %eax,-0x14000(%rsp)
  0x00000001060a1be7:   push     %rbp
  0x00000001060a1be8:   sub      $0x30,%rsp
  0x00000001060a1bec:   mov      0x8(%rcx),%r10d
  0x00000001060a1bf0:   cmp      $0xfb7aedc9,%r10d
  0x00000001060a1bf7:   jne      0x00000001060a1c39
  0x00000001060a1bf9:   mov      %rcx,%r10
  0x00000001060a1bfc:   mov      0x10(%r10),%ebp
  0x00000001060a1c00:   cmp      $0xfed77602,%ebp
  0x00000001060a1c06:   jne      0x00000001060a1c1e
  0x00000001060a1c08:   movabs   $0x7f6bf4bb0,%rax
  0x00000001060a1c12:   add      $0x30,%rsp
  0x00000001060a1c16:   pop      %rbp
  0x00000001060a1c17:   test     %eax,-0xec3c1d(%rip)
  0x00000001060a1c1d:   retq
i = 0
        while i < 10000
          1
          i+=1
        end
  0x00000001060a1be0:   mov      %eax,-0x14000(%rsp)
  0x00000001060a1be7:   push     %rbp
  0x00000001060a1be8:   sub      $0x30,%rsp
  0x00000001060a1bec:   mov      0x8(%rcx),%r10d
  0x00000001060a1bf0:   cmp      $0xfb7aedc9,%r10d
  0x00000001060a1bf7:   jne      0x00000001060a1c39
  0x00000001060a1bf9:   mov      %rcx,%r10
  0x00000001060a1bfc:   mov      0x10(%r10),%ebp
  0x00000001060a1c00:   cmp      $0xfed77602,%ebp
  0x00000001060a1c06:   jne      0x00000001060a1c1e
  0x00000001060a1c08:   movabs   $0x7f6bf4bb0,%rax
  0x00000001060a1c12:   add      $0x30,%rsp
  0x00000001060a1c16:   pop      %rbp
  0x00000001060a1c17:   test     %eax,-0xec3c1d(%rip)
  0x00000001060a1c1d:   retq
i = 0
        while i < 10000

          i+=1
        end
  0x00000001060a1be0:   mov      %eax,-0x14000(%rsp)
  0x00000001060a1be7:   push     %rbp
  0x00000001060a1be8:   sub      $0x30,%rsp
  0x00000001060a1bec:   mov      0x8(%rcx),%r10d
  0x00000001060a1bf0:   cmp      $0xfb7aedc9,%r10d
  0x00000001060a1bf7:   jne      0x00000001060a1c39
  0x00000001060a1bf9:   mov      %rcx,%r10
  0x00000001060a1bfc:   mov      0x10(%r10),%ebp
  0x00000001060a1c00:   cmp      $0xfed77602,%ebp
  0x00000001060a1c06:   jne      0x00000001060a1c1e
  0x00000001060a1c08:   movabs   $0x7f6bf4bb0,%rax
  0x00000001060a1c12:   add      $0x30,%rsp
  0x00000001060a1c16:   pop      %rbp
  0x00000001060a1c17:   test     %eax,-0xec3c1d(%rip)
  0x00000001060a1c1d:   retq
  0x00000001060a1be0:   mov      %eax,-0x14000(%rsp)
  0x00000001060a1be7:   push     %rbp
  0x00000001060a1be8:   sub      $0x30,%rsp
  0x00000001060a1bec:   mov      0x8(%rcx),%r10d
  0x00000001060a1bf0:   cmp      $0xfb7aedc9,%r10d
  0x00000001060a1bf7:   jne      0x00000001060a1c39
  0x00000001060a1bf9:   mov      %rcx,%r10
  0x00000001060a1bfc:   mov      0x10(%r10),%ebp
  0x00000001060a1c00:   cmp      $0xfed77602,%ebp
  0x00000001060a1c06:   jne      0x00000001060a1c1e
  0x00000001060a1c08:   movabs   $0x7f6bf4bb0,%rax
  0x00000001060a1c12:   add      $0x30,%rsp
  0x00000001060a1c16:   pop      %rbp
  0x00000001060a1c17:   test     %eax,-0xec3c1d(%rip)
  0x00000001060a1c1d:   retq
JRuby/Java 6   JRuby/Java 7
JRuby/Java 6                   JRuby/Java 7
                        Times Faster than Ruby 1.9.3
  5



3.75



 2.5



1.25



  0
       base64      richards        neural      mandelbrot     redblack
JRuby/Java 6                     JRuby/Java 7
                            Times Faster than Ruby 1.9.3
  5



3.75



 2.5

                                    1.914          1.806
                    1.538                                         1.565
1.25   1.346




  0
         base64      richards          neural      mandelbrot      redblack
JRuby/Java 6                     JRuby/Java 7
                                 Times Faster than Ruby 1.9.3
  5


                                                                4.226           4.32
3.75
                                                 3.66
                                 3.44


 2.5           2.658


                                         1.914          1.806
                         1.538                                          1.565
1.25   1.346




  0
         base64           richards          neural      mandelbrot       redblack