JRuby: Zero to Scale

F1d37642fdaa1662ff46e4c65731e9ab?s=47 headius
November 20, 2019

JRuby: Zero to Scale

JRuby is deployed by hundreds of companies, running Rails and other services at higher speeds and with better scalability than any other runtime. With JRuby you get better utilization of system resources, the performance and tooling of the JVM, and a massive collection of libraries to add to your toolbox.

In this talk, we'll cover:

* Getting started on JRuby
* Comparison to CRuby
* Building, migrating, and deploying apps
* Tuning, profiling, and monitoring
* Scaling considerations

F1d37642fdaa1662ff46e4c65731e9ab?s=128

headius

November 20, 2019
Tweet

Transcript

  1. 4.

    JRuby 9.2.9.0 • Lots of memory and startup time improvements

    • Better support for Java module system • .jruby.java_opts file to manage JVM options • Improved startup time for most commands • Dozens of issues fixed
  2. 6.

    Step 1: You Need a JVM • Java (version 8

    or 11 recommended) • Is it installed? java -version • If !installed • package install: dnf/apt install java • explicit install: http://adoptopenjdk.net
  3. 12.

    require 'benchmark' ary = (1..1000000).to_a loop { puts Benchmark.measure {

    10.times { ary.each {|i|} } } } Unthreaded require 'benchmark' ary = (1..1000000).to_a loop { puts Benchmark.measure { (1..10).map { Thread.new { ary.each {|i|} } }.map(&:join) } } Multi-threaded
  4. 14.

    Time (in seconds) 0 0.09 0.18 0.27 0.36 Unthreaded Threaded

    0.15 0.23 0.35 0.34 CRuby JRuby (lower is better)
  5. 16.

    Ruby Teams Hiro Marcin Nahi Subbu Douglas Christian Karol Tom

    Charlie Hiro charli Nahi zzak nurse hsbt matz ko1 nobu OS (libc, ...) JRuby MRI
  6. 17.

    Ruby Teams Hiro Marcin Nahi Subbu Douglas Christian Karol Tom

    Charlie Hiro charli Nahi zzak nurse hsbt matz ko1 nobu OS (libc, ...) JRuby MRI JVM POSIX
  7. 18.

    JVM Ruby Teams Hiro Marcin Nahi Subbu Douglas Christian Karol

    Tom Charlie Hiro charli Nahi zzak nurse hsbt matz ko1 nobu OS (libc, ...) JRuby MRI Better ??? POSIX
  8. 20.

    Shoulders of Giants JVM J. Rose J. Rose J. Rose

    J. Rose J. Rose J. Rose J. Rose J. Rose J. Rose Hiro Marcin Nahi Subbu Douglas Christian Dmitry Tom Charlie JRuby
  9. 21.

    All the stuff! JVM J. Rose J. Rose J. Rose

    J. Rose J. Rose J. Rose J. Rose J. Rose J. Rose Garbage Collection Native JIT Profiled Optimizations Native Threading Tooling Cross Platform
  10. 22.

    Alternate JVMs • Hotspot: standard OpenJDK Java VM • OpenJ9:

    open source version of IBM's J9 JVM • New GC and JIT tuning options • Startup time and JIT code-caching features • GraalVM: replaces Hotspot JIT with Graal JIT • New JIT optimizations, ahead-of-time native compilation
  11. 23.

    JVM is everywhere++! • Unix++, Windows • Exotic platforms: zLinux,

    OpenVMS, AS/400 • Mobile: Android’s Dalvik, Embedded JVMs
  12. 25.

    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!
  13. 28.

    C Extensions • API is massive • API is specific

    to C Ruby’s implementation • It is the implementation • At odds with concurrent Ruby execution • Huge support cost
  14. 29.

    Java Native Extensions • API is massive • API is

    specific to JRuby’s implementation • It is the implementation* • Allows Concurrent Ruby Execution • Support cost minimal • Common Gems Supported * We have plans for a formal API
  15. 30.

    oj: Optimized json • Fast json parsing and dumping with

    many options • Common transitive dependency with its own API • Needed for many popular apps/libraries https://github.com/ohler55/oj
  16. 31.

    oj for JRuby! • 9200 lines of Java (vs 20k

    lines of C) • Almost ready: 448 runs, 765 assertions, 43 failures, 12 errors • 35 F/E from minor features, date/time diffs
  17. 32.

    Load Performance 0M 0.3M 0.6M 0.9M 1.2M small medium large

    0.13 0.29 1.1 0.05 0.11 0.36 0.06 0.11 0.72 MRI (oj) JRuby (json) JRuby (oj) Millions of loads per second (higher is better) https://techblog.thescore.com/2014/05/23/benchmarking-json-generation-in-ruby/
  18. 33.

    Dump Performance 0 0.75 1.5 2.25 3 small medium large

    0.44 0.86 2.3 0.22 0.44 1.1 0.33 0.73 2.1 MRI (oj) JRuby (json) JRuby (oj) Million of dumps per second (higher is better) https://techblog.thescore.com/2014/05/23/benchmarking-json-generation-in-ruby/
  19. 35.

    Scripting Java • Access Java Classes using a Ruby Syntax

    • Java Libraries • Give alternatives to existing Ruby Libraries • Give access to APIs which do not exist in Ruby
  20. 36.
  21. 37.

    Fun Stuff event(:player_egg_throw) do |e| e.hatching = true e.num_hatches =

    120 e.player.mesg "hatched" end Purugin https://github.com/enebo/Purugin
  22. 39.

    Startup Time • Runtime optimizations give us excellent performance •

    ...eventually! • Startup time, warmup time are impacted • We continue working to reduce this impact • We compare some common commands
  23. 40.

    JRuby Architecture Ruby (.rb) JIT Java Instructions (java bytecode) Ruby

    Instructions (IR) parse interpret interpreter interpret C1 compile native code better native code java bytecode interpreter execute C2 compile Java Virtual Machine JRuby Internals deoptimize Performance improves the longer your app runs
  24. 41.

    JRuby Flag: --dev • export JRUBY_OPTS="--dev" • Disables JRuby's JIT

    • Reduces JVM JIT • Don't use when benchmarking! • 30-40% reduction • More improvements coming total execution time (lower is better) 0s 1.15s 2.3s 3.45s 4.6s gem list (~350 gems) 3.0s 4.6s JRuby JRuby --dev
  25. 44.

    OpenJDK Class Data Sharing • Pre-validate and cache class data

    • Save frequently-accessed data over time • Combined with --dev gives best current JRuby startup
  26. 45.

    Java 11 total execution time (lower is better) 0 1.75

    3.5 5.25 7 gem list (~350 gems) JRuby --dev --dev + CDS
  27. 46.

    App Performance • Sinatra and Roda • https://github.com/CaDs/ruby_benchmarks • Comparing

    JRuby, CRuby, and TruffleRuby • RedMine bug tracker and wiki • https://www.redmine.org/ • Real-world Rails application on JRuby, CRuby
  28. 47.

    Peak Performance • After initial startup, warmup, data caching •

    JRuby generally gives better peak performance • Be aware of warmup time
  29. 48.

    Sinatra and Roda requests/second (higher is better) 0 12500 25000

    37500 50000 Sinatra Roda 5,214 4,257 44,703 42,468 14,489 12,284 CRuby JRuby TruffleRuby
  30. 49.

    Redmine Issue View, rendered and json (higher is better) 0

    req/s 35 req/s 70 req/s 105 req/s 140 req/s issues/13 issues/13.json 137 req/s 50 req/s 91 req/s 41 req/s CRuby 2.6.2 JRuby 9.2.9
  31. 50.

    Warmup Time • Large applications take longer to warm up

    • Working on new JIT metrics, profiling to reduce this curve
  32. 53.

    Redmine issues/13.json warmup, one-minute cycles 0 35 70 105 140

    1st 2nd 3rd 4th 5th 6th CRuby 2.6.2 JRuby 9.2.9
  33. 54.

    Redmine memory usage (lower is better) 0MB 375MB 750MB 1125MB

    1500MB Memory usage for 8 workers vs 8 threads 800MB 1,430MB 1,100MB CRuby JRuby (default) JRuby (300MB heap)
  34. 56.

    Migration Process • Existing application Activities: • Configuration Changes (e.g.

    config/database.yml) • C extensions replacement • Thread-safety audit
  35. 57.

    Use-Case: Discourse • “A platform for community discussion” • Very

    large, well-known Rails application • >500 gems • 250,000 lines of Ruby • JRuby is not currently supported • But it is almost working!
  36. 59.

    jruby-lint gem See how ready your Ruby code is to

    run on JRuby $ gem install jruby-lint $ cd my-app $ jrlint
  37. 60.

    [] ~/projects/discourse $ jrlint JRuby-Lint version 0.9.0 ./Gemfile:: [gems, info]

    For more on gem compatibility see http://wiki.jruby.org/C-Extension-Alternatives ./Gemfile:80: [gems, warning] Found gem 'oj' which is reported to have some issues: Try `gson`, `json` or `json_pure` instead.| gem 'oj' ./Gemfile:81: [gems, warning] Found gem 'pg' which is reported to have some issues: Use activerecord-jdbcpostgresql-adapter instead or pg_jruby (drop-in replacement).| gem 'pg' ./Gemfile:187: [gems, warning] Found gem 'mysql2' which is reported to have some issues: Use activerecord-jdbcmysql-adapter.| gem 'mysql2' ./Gemfile:188: [gems, warning] Found gem 'redcarpet' which is reported to have some issues: Same as with **RDiscount** use alternatives such as kramdown, Maruku or markdown_j| gem 'redcarpet' ./Gemfile:189: [gems, warning] Found gem 'sqlite3' which is reported to have some issues: Use activerecord-jdbcsqlite3-adapter.| gem 'sqlite3', '~> 1.3.13' ./app/mailers/user_notifications.rb:152: [nonatomic, warning] Non-local operator assignment (@popular_topics) is not guaranteed to be atomic. @popular_topics = topics_for_digest[0, SiteSetting.digest_topics] ./app/mailers/user_notifications.rb:630: [nonatomic, warning] Non-local operator assignment (@site_name) is not guaranteed to be atomic. @site_name = SiteSetting.email_prefix.presence || SiteSetting.title # used by I18n ./app/models/report.rb:21: [nonatomic, warning] Non-local operator assignment (@start_date) is not guaranteed to be atomic. @start_date ||= Report.default_days.days.ago.utc.beginning_of_day ./app/models/report.rb:22: [nonatomic, warning] Non-local operator assignment (@end_date) is not guaranteed to be atomic. @end_date ||= Time.now.utc.end_of_day ./app/models/admin_dashboard_next_data.rb:17: [nonatomic, warning] Non-local operator assignment (@json) is not guaranteed to be atomic. @json ||= get_json ./app/models/topic_posters_summary.rb:31: [nonatomic, warning] Non-local operator assignment (@descriptions_by_id) is not guaranteed to be atomic. @descriptions_by_id ||= begin ./app/models/topic_posters_summary.rb:33: [nonatomic, warning] Non-local operator assignment (descriptions[id]) is not guaranteed to be atomic. descriptions[id] ||= [] ./app/models/topic_posters_summary.rb:79: [nonatomic, warning] Non-local operator assignment (@avatar_lookup) is not guaranteed to be atomic. @avatar_lookup ||= options[:avatar_lookup] || AvatarLookup.new(user_ids) ./app/models/topic_posters_summary.rb:83: [nonatomic, warning] Non-local operator assignment (@primary_group_lookup) is not guaranteed to be atomic. @primary_group_lookup ||= options[:primary_group_lookup] || PrimaryGroupLookup.new(user_ids) ./app/models/directory_item.rb:8: [nonatomic, warning] Non-local operator assignment (@headings) is not guaranteed to be atomic. @headings ||= [:likes_received, ./app/models/directory_item.rb:18: [nonatomic, warning] Non-local operator assignment (@types) is not guaranteed to be atomic. @types ||= Enum.new(all: 1, ./app/models/group_history.rb:11: [nonatomic, warning] Non-local operator assignment (@actions) is not guaranteed to be atomic. @actions ||= Enum.new( ./app/models/locale_site_setting.rb:10: [nonatomic, warning] Non-local operator assignment (@values) is not guaranteed to be atomic. @values ||= supported_locales.map do |locale| ./app/models/locale_site_setting.rb:25: [nonatomic, warning] Non-local operator assignment (@language_names) is not guaranteed to be atomic. @language_names ||= begin ./app/models/locale_site_setting.rb:41: [nonatomic, warning] Non-local operator assignment (@supported_locales) is not guaranteed to be atomic. @supported_locales ||= begin ./app/models/category.rb:98: [nonatomic, warning] Non-local operator assignment (TOPIC_CREATION_PERMISSIONS) is not guaranteed to be atomic. TOPIC_CREATION_PERMISSIONS ||= [:full] ./app/models/category.rb:99: [nonatomic, warning] Non-local operator assignment (POST_CREATION_PERMISSIONS) is not guaranteed to be atomic. POST_CREATION_PERMISSIONS ||= [:create_post, :full] ./app/models/category.rb:109: [nonatomic, warning] Non-local operator assignment (@topic_id_cache) is not guaranteed to be atomic. @topic_id_cache = DistributedCache.new('category_topic_ids') ./app/models/category.rb:228: [nonatomic, warning] Non-local operator assignment (@@cache) is not guaranteed to be atomic. @@cache ||= LruRedux::ThreadSafeCache.new(1000) ./app/models/category.rb:520: [nonatomic, warning] Non-local operator assignment (@has_children) is not guaranteed to be atomic. @has_children ||= (id && Category.where(parent_category_id: id).exists?) ? :true : :false
  38. 61.

    Unsupported Extensions ./Gemfile:: [gems, info] For more on gem compatibility

    see http://wiki.jruby.org/C-Extension-Alternatives ./Gemfile:80: [gems, warning] Found gem 'oj' which is reported to have some issues: Try `gson`, `json` or `json_pure` instead.| gem 'oj' ./Gemfile:81: [gems, warning] Found gem 'pg' which is reported to have some issues: Use activerecord-jdbcpostgresql-adapter instead or pg_jruby (drop-in replacement).| gem 'pg' ./Gemfile:187: [gems, warning] Found gem 'mysql2' which is reported to have some issues: Use activerecord-jdbcmysql-adapter.| gem 'mysql2' ./Gemfile:188: [gems, warning] Found gem 'redcarpet' which is reported to have some issues: Same as with **RDiscount** use alternatives such as kramdown, Maruku or markdown_j| gem 'redcarpet' ./Gemfile:189: [gems, warning] Found gem 'sqlite3' which is reported to have some issues: Use activerecord-jdbcsqlite3-adapter.| gem 'sqlite3', '~> 1.3.13'
  39. 62.
  40. 63.

    Threading Concerns ./app/models/report.rb:21: [nonatomic, warning] Non-local operator assignment (@start_date) is

    not guaranteed to be atomic. @start_date ||= Report.default_days.days.ago.utc.beginning_of_day ./app/models/report.rb:22: [nonatomic, warning] Non-local operator assignment (@end_date) is not guaranteed to be atomic. @end_date ||= Time.now.utc.end_of_day ./app/models/admin_dashboard_next_data.rb:17: [nonatomic, warning] Non-local operator assignment (@json) is not guaranteed to be atomic. @json ||= get_json ./app/models/topic_posters_summary.rb:31: [nonatomic, warning] Non-local operator assignment (@descriptions_by_id) is not guaranteed to be atomic. @descriptions_by_id ||= begin ./app/models/topic_posters_summary.rb:33: [nonatomic, warning] Non-local operator assignment (descriptions[id]) is not guaranteed to be atomic. descriptions[id] ||= [] ./app/models/topic_posters_summary.rb:79: [nonatomic, warning] Non-local operator assignment (@avatar_lookup) is not guaranteed to be atomic. @avatar_lookup ||= options[:avatar_lookup] || AvatarLookup.new(user_ids) ./app/models/topic_posters_summary.rb:83: [nonatomic, warning] Non-local operator assignment (@primary_group_lookup) is not guaranteed to be atomic. @primary_group_lookup ||= options[:primary_group_lookup] || PrimaryGroupLookup.new(user_ids) @language_names) is not guaranteed to be atomic. @language_names ||= begin
  41. 64.

    Unsupported Features ./script/measure.rb:48: [objectspace, warning] Use of ObjectSpace is expensive

    and disabled by default. Use -X+O to enable. ObjectSpace.each_object do |o| ./script/check_forking.rb:14: [fork, error] Kernel#fork is not implemented on JRuby. child = fork do ./script/check_forking.rb:17: [fork, error] Kernel#fork is not implemented on JRuby. grand_child = fork do
  42. 66.

    % bundle install Fetching pg 1.1.4 Installing pg 1.1.4 with

    native extensions Gem::Ext::BuildError: ERROR: Failed to build gem native extension gem 'pg' Gemfile Gemfile gem 'pg', platform: :mri gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby
  43. 67.

    Missing C Extension 1.Remove it if not needed (development dep

    like byebug) 2.Use a pure-Ruby version if performance is good enough 3.Call into a native library using FFI (Foreign Function Interface) 4.“Script” a Java library 5.Write a JRuby extension
  44. 68.

    Step 3: Run It • Once your application bundles, it

    should run! • If not talk to us or file an issue puma -t 20:20 -e production
  45. 70.

    JVM Tooling • Visual VM: monitor and profile threads, GC,

    managed heap • Mission Control: visualize Flight Recorder output • Flight Recorder: low-overhead system profiling in OpenJDK • async-profiler: command line profiles, flame graphs of CPU, alloc • All JVM tools work to monitor and profile JRuby apps
  46. 71.

    VisualVM • Standalone graphical console for monitoring, profiling • Open

    sourced as part of OpenJDK project • https://visualvm.github.io/
  47. 72.
  48. 74.

    JDK Flight Recorder • JVM flag: -XX:+FlightRecorder • JRuby flag:

    -J-XX:+FlightRecorder or put in JAVA_OPTS • Add --flight-recorder to JRuby launcher? • No overhead or profiling until you start recording • And usually less than 1% overhead for that
  49. 75.

    JDK Mission Control • Control center and visualizer for Flight

    Recorder data • Start and manage recordings • Browse recorded data • https://adoptopenjdk.net/jmc.html
  50. 76.
  51. 77.
  52. 78.
  53. 79.
  54. 80.
  55. 81.
  56. 82.

    async-profiler • JVM extension for lightweight sampled profiles • Install

    jruby-async-profiler gem • jruby -J-agentpath:<jruby home>/lib/libasyncProfiler.so • Simplified command lines coming soon • See https://github.com/jvm-profiling-tools/async-profiler
  57. 83.
  58. 85.

    Getting Help • JRuby on GitHub: https://github.com/jruby/jruby • Issues, Wiki

    • Chat with JRuby devs, users • jruby on Matrix • #jruby on Freenode IRC • Mailing list: https://lists.ruby-lang.org
  59. 86.

    During Development • JRUBY_OPTS=--dev • BE WARY of .ruby-version •

    Don’t share gem paths between Ruby implementations • Java and C extensions clobber each other
  60. 87.

    Java Modules • Java 9+ introduced Java Modules • You'll

    see warnings about JRuby or Ruby accesses • New config file for JVM flags: .jruby.java_opts • Gather JVM options into a single file • Current dir, home dir, JRuby bin/ dir
  61. 88.

    Java Modules and .jruby.java_opts WARNING: An illegal reflective access operation

    has occurred WARNING: Illegal reflective access by org.bouncycastle.jcajce.provider.drbg.DRBG (file:/Users/headius/.m2/repository/org/ bouncycastle/bcprov-jdk15on/1.61/bcprov-jdk15on-1.61.jar) to constructor sun.security.provider.Sun() WARNING: Please consider reporting this to the maintainers of org.bouncycastle.jcajce.provider.drbg.DRBG WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release --add-opens java.base/java.io=org.jruby.dist --add-opens java.base/java.nio.channels=org.jruby.dist --add-opens java.base/sun.nio.ch=org.jruby.dist --add-opens java.management/sun.management=org.jruby.dist
  62. 91.

    Thank You! • @headius, @tom_enebo • https://www.jruby.org • https://github.com/jruby/jruby •

    Chat with JRuby devs, users • #jruby on Freenode IRC • jruby on Matrix • Mailing list: https://lists.ruby-lang.org