Slide 1

Slide 1 text

Why JRuby? Monday, November 12, 12

Slide 2

Slide 2 text

Who? Thomas @tom_enebo Charlie @headius Monday, November 12, 12

Slide 3

Slide 3 text

What is JRuby? Monday, November 12, 12

Slide 4

Slide 4 text

JRuby is Ruby! 1.8.7 & 1.9.3 compatibility drop-in replacement * * see next slide Monday, November 12, 12

Slide 5

Slide 5 text

*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... Monday, November 12, 12

Slide 6

Slide 6 text

JRuby is Ruby ...and then some? Monday, November 12, 12

Slide 7

Slide 7 text

Announcing JRuby 1.7.0 • Ruby 1.9.3 compat (--1.8 for 1.8.7) • Java 7 invokedynamic support • Much awesomeness over 1.6.x Monday, November 12, 12

Slide 8

Slide 8 text

Getting Started 1. Install a JVM 2. rvm install jruby 3. Profit! % jruby -e ‘puts “wowee”’ Monday, November 12, 12

Slide 9

Slide 9 text

The JRuby Difference Monday, November 12, 12

Slide 10

Slide 10 text

JRuby Team Charlie Tom Nick Hiro Marcin Nahi Wayne Subbu Douglas Douglas Contribs Douglas Douglas OpenJDK Douglas Douglas Android Douglas Douglas Other JVMs Douglas Monday, November 12, 12

Slide 11

Slide 11 text

JRuby OS (libc, ...) JRuby JVM Yoko J. Rose Monday, November 12, 12

Slide 12

Slide 12 text

MRI OS (libc, ...) MRI nobu Monday, November 12, 12

Slide 13

Slide 13 text

JRuby OS (libc, ...) JRuby JVM Yoko J. Rose Monday, November 12, 12

Slide 14

Slide 14 text

We get it for Free! JVM J. Rose Garbage Collection Native JIT Profiled Optimizations Native Threading Tooling Cross Platform Monday, November 12, 12

Slide 15

Slide 15 text

Profile: John Rose • JVM Engineer since 1997 • Invented C* Language • JSR 292 lead Monday, November 12, 12

Slide 16

Slide 16 text

JVM over time (what if we were lazy?) Monday, November 12, 12

Slide 17

Slide 17 text

0 7.5 15 22.5 30 Java 1.4 Java 5 Java 6 Java 7 Go Java Go! JRuby 1.0.3 (bm_red_black_tree.rb) 300% for free Monday, November 12, 12

Slide 18

Slide 18 text

0 7.5 15 22.5 30 Java 1.4 Java 5 Java 6 Java 7 Go Java Go! JRuby 1.0.3 (bm_red_black_tree.rb) MRI 1.8 300% for free Monday, November 12, 12

Slide 19

Slide 19 text

JVM Benefits Monday, November 12, 12

Slide 20

Slide 20 text

Cross-Platform Monday, November 12, 12

Slide 21

Slide 21 text

JVM is everywhere • Unix++, Windows • Exotic platforms: zLinux, OpenVMS, AS/400 • Mobile: Android’s Dalvik, Embedded JVMs Monday, November 12, 12

Slide 22

Slide 22 text

Monday, November 12, 12

Slide 23

Slide 23 text

Java bytecode == portability Monday, November 12, 12

Slide 24

Slide 24 text

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 Monday, November 12, 12

Slide 25

Slide 25 text

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 No build tools! Monday, November 12, 12

Slide 26

Slide 26 text

Libraries 47k libraries in Maven Hadoop EHCache Selenium Sitemesh Lucene Neo4j JMonkeyEngine Monday, November 12, 12

Slide 27

Slide 27 text

Languages/Polyglot Clojure Scala Groovy Jython Rhino/Nashorn/ DynJS (JavaScript) Micro Focus JVM Visual COBOL Monday, November 12, 12

Slide 28

Slide 28 text

Polyglot • Use right tool for the right job • Running in the same VM • Another dimension of libraries Monday, November 12, 12

Slide 29

Slide 29 text

GC Monday, November 12, 12

Slide 30

Slide 30 text

GC Matters • Applications grow over time • Ruby is very object-heavy • Multiprocess multiplies the problem • You will eventually have issues Monday, November 12, 12

Slide 31

Slide 31 text

JVM GC • Wide array of options • Many GCs to choose from • Scales up to massive heaps • Best GCs in the world! Monday, November 12, 12

Slide 32

Slide 32 text

OpenJDK GCs • Parallel: multi-core stop-the-world • Concurrent: STW young, concurrent old • G1: concurrent young and old • Serial: single-thread STW Monday, November 12, 12

Slide 33

Slide 33 text

Object Homogeneity • Everything expressed as JVM objects • Everything shares the same infrastructure • Including extensions, libraries, etc • One GC to rule them all • And one standard memory model Monday, November 12, 12

Slide 34

Slide 34 text

gc_demo.rb • Heavy GC, mix of old and young • Steadily growing heap use Monday, November 12, 12

Slide 35

Slide 35 text

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 } Monday, November 12, 12

Slide 36

Slide 36 text

0 2000 4000 6000 8000 GC count Ruby 1.9.3 JRuby Monday, November 12, 12

Slide 37

Slide 37 text

1 10 100 1000 10000 GC count Ruby 1.9.3 JRuby Monday, November 12, 12

Slide 38

Slide 38 text

0 3.75 7.5 11.25 15 GC time % Ruby 1.9.3 JRuby Monday, November 12, 12

Slide 39

Slide 39 text

0ms 75ms 150ms 225ms 300ms 188KB/29MB 27MB/127MB 199MB/238MB Time per GC versus heap usage Time per GC Heap usage (MRI/JRuby) Ruby 2.0.0 JRuby Monday, November 12, 12

Slide 40

Slide 40 text

:-) :-| :-/ :-( :-( 188KB/29MB 27MB/127MB 199MB/238MB Time per GC versus heap usage User Unhappiness Heap usage (MRI/JRuby) Ruby 2.0.0 JRuby Monday, November 12, 12

Slide 41

Slide 41 text

0 1,000 2,000 3,000 4,000 0M 1,250M 2,500M 3,750M 5,000M Time Per GC (ms) Heap Size Ruby 2.0.0 Monday, November 12, 12

Slide 42

Slide 42 text

Findings • Lower, more uniform GC times • Reduced or eliminated pauses • Very large heaps are no problem • Predictable, consistent experience Monday, November 12, 12

Slide 43

Slide 43 text

Threads Monday, November 12, 12

Slide 44

Slide 44 text

Real Parallellism • Ruby thread = JVM thread = native thread • One process can use all cores • One server can handle all requests Monday, November 12, 12

Slide 45

Slide 45 text

require 'benchmark' ary = (1..1000000).to_a loop { puts Benchmark.measure { 10.times { ary.each {|i|} } } } Monday, November 12, 12

Slide 46

Slide 46 text

require 'benchmark' ary = (1..1000000).to_a loop { puts Benchmark.measure { (1..10).map { Thread.new { ary.each {|i|} } }.map(&:join) } } Monday, November 12, 12

Slide 47

Slide 47 text

Monday, November 12, 12

Slide 48

Slide 48 text

Ruby 1.9 unthreaded Monday, November 12, 12

Slide 49

Slide 49 text

Ruby 1.9 unthreaded Ruby 1.9 threaded Monday, November 12, 12

Slide 50

Slide 50 text

Ruby 1.9 unthreaded Ruby 1.9 threaded JRuby unthreaded Monday, November 12, 12

Slide 51

Slide 51 text

Ruby 1.9 unthreaded Ruby 1.9 threaded JRuby unthreaded JRuby threaded Monday, November 12, 12

Slide 52

Slide 52 text

0.2s 0.35s 0.5s 0.65s 0.8s one thread two threads three threads four threads Per-iteration time versus thread count threaded_reverse Monday, November 12, 12

Slide 53

Slide 53 text

Nonlinear? • More work means more objects • Allocation/GC needs memory bandwidth • No different from multi-process Monday, November 12, 12

Slide 54

Slide 54 text

Monday, November 12, 12

Slide 55

Slide 55 text

Tools Monday, November 12, 12

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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 Monday, November 12, 12

Slide 58

Slide 58 text

VisualVM • CPU, memory, thread monitoring • CPU and memory profiling • VisualGC • Heap analysis Monday, November 12, 12

Slide 59

Slide 59 text

Monday, November 12, 12

Slide 60

Slide 60 text

Monday, November 12, 12

Slide 61

Slide 61 text

Monday, November 12, 12

Slide 62

Slide 62 text

Monday, November 12, 12

Slide 63

Slide 63 text

Monday, November 12, 12

Slide 64

Slide 64 text

Monday, November 12, 12

Slide 65

Slide 65 text

JRuby Goodies Monday, November 12, 12

Slide 66

Slide 66 text

Scripting Java Monday, November 12, 12

Slide 67

Slide 67 text

JavaFX straight port Simple Clock Monday, November 12, 12

Slide 68

Slide 68 text

@minute_hand = Path.new.tap do |mh| mh.setFill(Color::BLACK) mh.getElements.add MoveTo.new(4, -4) mh.getElements.add ArcTo.new(-1, -1, 0, -4, -4, false, false) mh.getElements.add LineTo.new(0, -radius) mh.getTransforms.add Rotate.new end class Refresher include EventHandler def handle(event); event.source.refresh; end end Timeline.new.tap do |time| time.setCycleCount Timeline::INDEFINITE time.getKeyFrames.add(Keyframe.new(Duration.millis(1000)), Refresher.new) time.play end Draw minute hand Implement Java Event handler refresh timeline every 1s Monday, November 12, 12

Slide 69

Slide 69 text

getFooBar -> fooBar @minute_hand = Path.new.tap do |mh| mh.setFill(Color::BLACK) mh.elements.add MoveTo.new(4, -4) mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false) mh.elements.add LineTo.new(0, -radius) mh.transforms.add Rotate.new end class Refresher include EventHandler def handle(event); event.source.refresh; end end Timeline.new.tap do |time| time.setCycleCount Timeline::INDEFINITE time.keyFrames.add(Keyframe.new(Duration.millis(1000)), Refresher.new) time.play end was getElements was getTransforms was getKeyFrames Monday, November 12, 12

Slide 70

Slide 70 text

setFoo(a) -> foo = a @minute_hand = Path.new.tap do |mh| mh.fill = Color::BLACK mh.elements.add MoveTo.new(4, -4) mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false) mh.elements.add LineTo.new(0, -radius) mh.transforms.add Rotate.new end class Refresher include EventHandler def handle(event); event.source.refresh; end end Timeline.new.tap do |time| time.cycleCount = Timeline::INDEFINITE time.keyFrames.add(Keyframe.new(Duration.millis(1000)), Refresher.new) time.play end was setFill was setCycleCount Monday, November 12, 12

Slide 71

Slide 71 text

camelCase -> camel_case @minute_hand = Path.new.tap do |mh| mh.fill = Color::BLACK mh.elements.add MoveTo.new(4, -4) mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false) mh.elements.add LineTo.new(0, -radius) mh.transforms.add Rotate.new end class Refresher include EventHandler def handle(event); event.source.refresh; end end Timeline.new.tap do |time| time.cycle_count = Timeline::INDEFINITE time.key_frames.add(Keyframe.new(Duration.millis(1000)), Refresher.new) time.play end was cycleCount was keyFrames Monday, November 12, 12

Slide 72

Slide 72 text

Procs as interfaces @minute_hand = Path.new.tap do |mh| mh.fill = Color::BLACK mh.elements.add MoveTo.new(4, -4) mh.elements.add ArcTo.new(-1, -1, 0, -4, -4, false, false) mh.elements.add LineTo.new(0, -radius) mh.transforms.add Rotate.new end Timeline.new.tap do |time| time.cycle_count = Timeline::INDEFINITE time.key_frames.add Keyframe.new(Duration.millis(1000)) {refresh} time.play end No more extra class Monday, November 12, 12

Slide 73

Slide 73 text

Common Adornments @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 Timeline.new.tap do |time| time.cycle_count = Timeline::INDEFINITE time.key_frames << Keyframe.new(Duration.millis(1000)) {refresh} time.play end ‘add’ becomes ‘<<‘ Monday, November 12, 12

Slide 74

Slide 74 text

Purugin • Minecraft scripting in JRuby • Clean and simple DSL • Purogo: LOGO for Minecraft Monday, November 12, 12

Slide 75

Slide 75 text

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 Monday, November 12, 12

Slide 76

Slide 76 text

Monday, November 12, 12

Slide 77

Slide 77 text

https://github.com/enebo/Purugin Pimping a side-project Monday, November 12, 12

Slide 78

Slide 78 text

Java Native Extensions Monday, November 12, 12

Slide 79

Slide 79 text

“Look, nobody enjoys shooting penguins, but if you have to shoot penguins, well, you might as well enjoy it.” - Free Waterfall Sr. Native Extensions Suck Monday, November 12, 12

Slide 80

Slide 80 text

Flowchart of Shame Can I write it in Ruby? Does it need to be n times faster? Can I use FFI? Native Extension yes no no no Script Java? no Monday, November 12, 12

Slide 81

Slide 81 text

Java Native Extensions • Written in Java • Have same performance as Java • Use same GC as JRuby • First Class Citizens Monday, November 12, 12

Slide 82

Slide 82 text

Performance Monday, November 12, 12

Slide 83

Slide 83 text

0 7.5 15 22.5 30 Java 1.4 Java 5 Java 6 Java 7 Go Java Go! JRuby 1.0.3 (bm_red_black_tree.rb) 300% for free Monday, November 12, 12

Slide 84

Slide 84 text

0 2 4 6 8 1.0.3 1.1.6 1.4.0 1.5.6 1.6.8 1.7.0 OpenJDK 8 (bm_red_black_tree.rb) Go JRuby Go! Monday, November 12, 12

Slide 85

Slide 85 text

0 2.25 4.5 6.75 9 1.0.3 1.1.6 1.4.0 1.5.6 1.6.8 1.7.0 OpenJDK 8 (bm_red_black_tree.rb) Severe perf bottleneck(s) Severe gains??? Monday, November 12, 12

Slide 86

Slide 86 text

1.0.3 & red_black_tree [GC (Allocation Failure) 223608K->96408K(330752K), 0.0159780 secs] [GC (Allocation Failure) 208920K->100792K(335168K), 0.0157550 secs] [GC (Allocation Failure) 213304K->105144K(332160K), 0.0181010 secs] [GC (Allocation Failure) 205112K->108920K(334400K), 0.0187580 secs] [GC (Allocation Failure) 208888K->112712K(329152K), 0.0154440 secs] 8.1s -J-verbose:gc [GC (Allocation Failure) 313780K->199892K(339072K), 0.0142010 secs] [GC (Allocation Failure) 318420K->204420K(331520K), 0.0175690 secs] [GC (Allocation Failure) 306948K->208316K(335680K), 0.0188120 secs] [Full GC (Ergonomics) 208316K->54991K(352256K), 0.2709750 secs] [GC (Allocation Failure) 157519K->58959K(349248K), 0.0120840 secs] 8.4s Moar Objects! +28 more +28 more +28 more +28 more Monday, November 12, 12

Slide 87

Slide 87 text

1.7.0 & red_black_tree +28 more [GC (Allocation Failure) 155729K->39697K(207296K), 0.0072730 secs] 0.963s [GC (Allocation Failure) 160785K->40657K(208320K), 0.0108620 secs] 0.968s [GC (Allocation Failure) 161745K->41649K(210112K), 0.0083760 secs] 0.968s [GC (Allocation Failure) 166193K->39729K(210688K), 0.0070670 secs] 0.99s -J-verbose:gc Monday, November 12, 12

Slide 88

Slide 88 text

0 0.75 1.5 2.25 3 1.1.6 1.4.0 1.5.6 1.6.8 1.7.0 OpenJDK 8 (bm_red_black_tree.rb) Monday, November 12, 12

Slide 89

Slide 89 text

0 0.75 1.5 2.25 3 1.1.6 1.4.0 1.5.6 1.6.8 1.7.0 OpenJDK 8 (bm_red_black_tree.rb) JVM Feature! Monday, November 12, 12

Slide 90

Slide 90 text

Performance • JRuby compiles Ruby to JVM bytecode • JVM compiles bytecode to native • Best JIT technology in the world • Getting even better with invokedynamic Monday, November 12, 12

Slide 91

Slide 91 text

How to Optimize Ruby • Do less work • Reduce dispatch and call overhead • Reduce memory overhead • Find static patterns • Profile running code • Emit optimized version with guards Monday, November 12, 12

Slide 92

Slide 92 text

JVM Optimizations • Profiling • Watch code, optimize hottest paths • Inlining • Combine code, optimize as a whole • Escape analysis • Eliminate transient objects Monday, November 12, 12

Slide 93

Slide 93 text

def foo; Object.new; end def invoker; foo; end i = 0 while i < 10000 invoker i+=1 end Monday, November 12, 12

Slide 94

Slide 94 text

def invoker; Object.new; end i = 0 while i < 10000 invoker i+=1 end Inline foo into invoker Monday, November 12, 12

Slide 95

Slide 95 text

i = 0 while i < 10000 Object.new i+=1 end Inline invoker into loop Monday, November 12, 12

Slide 96

Slide 96 text

i = 0 while i < 10000 i+=1 end Object is transient Monday, November 12, 12

Slide 97

Slide 97 text

i = 10000 Loop does nothing Monday, November 12, 12

Slide 98

Slide 98 text

Variable i is never read Monday, November 12, 12

Slide 99

Slide 99 text

InvokeDynamic • Java 7+ feature • Allows us to teach JVM about Ruby • Dynamic calls can inline • Constants become truly constant • JVM’s best optimizations can work Monday, November 12, 12

Slide 100

Slide 100 text

Does It Work? Monday, November 12, 12

Slide 101

Slide 101 text

def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 102

Slide 102 text

$ jruby -J-XX:+UnlockDiagnosticVMOptions \ -J-XX:+PrintInlining \ -J-XX:+PrintCompilation \ script.rb 79 1 b java.lang.String::hashCode (55 bytes) 109 2 b java.util.Properties$LineReader::readLine (452 bytes) @ 48 java.io.Reader::read (9 bytes) never executed @ 62 java.io.FilterInputStream::read (9 bytes) @ 303 java.lang.System::arraycopy (0 bytes) (intrinsic) @ 388 java.io.Reader::read (9 bytes) never executed .... Monday, November 12, 12

Slide 103

Slide 103 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 104

Slide 104 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 105

Slide 105 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 106

Slide 106 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 107

Slide 107 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 108

Slide 108 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 109

Slide 109 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 110

Slide 110 text

3321 190 b ruby.__dash_e__::block_0$RUBY$__file__ (83 bytes) @ 6 org.jruby.RubyFixnum::op_lt (22 bytes) inline (hot) @ 66 org.jruby.RubyBasicObject::isTrue (15 bytes) inline (hot) @ 6 ruby.__dash_e__::method__1$RUBY$invoker (9 bytes) inline (hot) @ 6 ruby.__dash_e__::method__0$RUBY$foo (7 bytes) inline (hot) @ 5 org.jruby.RubyFixnum::op_plus_one (31 bytes) inline (hot) def foo; 1; end def invoker; foo; end N.times do i = 0 while i < 10000 invoker i+=1 end end Monday, November 12, 12

Slide 111

Slide 111 text

Does It Help? Monday, November 12, 12

Slide 112

Slide 112 text

Monday, November 12, 12

Slide 113

Slide 113 text

JRuby/Java 6 JRuby/Java 7 Monday, November 12, 12

Slide 114

Slide 114 text

base64 richards neural mandelbrot redblack 0 1.25 2.5 3.75 5 Times Faster than Ruby 1.9.3 JRuby/Java 6 JRuby/Java 7 Monday, November 12, 12

Slide 115

Slide 115 text

base64 richards neural mandelbrot redblack 0 1.25 2.5 3.75 5 1.346 1.538 1.914 1.806 1.565 Times Faster than Ruby 1.9.3 JRuby/Java 6 JRuby/Java 7 Monday, November 12, 12

Slide 116

Slide 116 text

base64 richards neural mandelbrot redblack 0 1.25 2.5 3.75 5 1.346 1.538 1.914 1.806 1.565 2.658 3.44 3.66 4.226 4.32 Times Faster than Ruby 1.9.3 JRuby/Java 6 JRuby/Java 7 Monday, November 12, 12

Slide 117

Slide 117 text

smooth_sort # Original Author: Keith Schwarz ([email protected]) # # Translated to Ruby by Chuck Remes (chuckremes on github) # # An implementation of Dijkstra's Smoothsort algorithm, a modification of # heapsort that runs in O(n lg n) in the worst case, but O(n) if the data # are already sorted. For more information about how this algorithm works # and some of the details necessary for its proper operation, please see # # http://www.keithschwarz.com/smoothsort/ Monday, November 12, 12

Slide 118

Slide 118 text

0 25000 50000 75000 100000 Iterations per second 19590.7 11439 4750 Ruby 1.8.7 Ruby 1.9.3 Ruby 2.0.0 JRuby Monday, November 12, 12

Slide 119

Slide 119 text

And Rails? Monday, November 12, 12

Slide 120

Slide 120 text

Monday, November 12, 12

Slide 121

Slide 121 text

Monday, November 12, 12

Slide 122

Slide 122 text

Monday, November 12, 12

Slide 123

Slide 123 text

Your Turn • Try your apps on JRuby and tell us • Turn on JRuby in @travisci • Let us know what you think of JRuby • Help us make JRuby even better! • JRuby BOF in Room C at 6:30PM Monday, November 12, 12

Slide 124

Slide 124 text

JRUBY BOOK Monday, November 12, 12

Slide 125

Slide 125 text

Monday, November 12, 12

Slide 126

Slide 126 text

Thank you! • @headius • jruby.org • torquebox.org Monday, November 12, 12