Browse Source

sinatra-sequel updates (#2498)

* Update Rubies to latest minors/patchlevels and add Ruby 2.4

* Round 14 prep for sinatra-sequel

* Annotate tests with test number and title
* We are not required to check Accept request header, so don't (use
  `content_type' helper instead of `provides' condition)
* Add support and benchmarks for Postgres
* Add initial support for Windows (kinda)
* Improve Server and Date response headers
* Ruby and Bundle updates (Sinatra 2.0!)
* Reintroduce JRuby benchmarks (hooray!)
* Take advantage of some Ruby 2.3 features
* Use JSON.fast_generate instead of Sequel::Plugins::JsonSerializer
* Add Sysrandom to improve random number generator performance
* Rework Puma workers/threads configuration around MAX_CONCURRENCY

* Update JRuby 1.7 and JRuby 9K (and rename to 9.0) and add JRuby 9.1
Mike Pastore 8 years ago
parent
commit
20682b2a30

+ 17 - 7
frameworks/Ruby/sinatra-sequel/Gemfile

@@ -1,9 +1,19 @@
 source 'https://rubygems.org'
 
-gem 'jdbc-mysql', '~> 5.1.38', :platform => 'jruby', :require => 'jdbc/mysql'
-gem 'json', '~> 1.8.3', :require => 'json/ext'
-gem 'mysql2', '~> 0.4.0', :platform => 'ruby'
-gem 'puma', '~> 2.15.3'
-gem 'sequel', '~> 4.28'
-gem 'sinatra', '~> 1.4.6', :require => 'sinatra/base'
-gem 'slim', '~> 3.0.6'
+gem 'json', '~> 2.0'
+gem 'puma', '~> 3.6', :require=>false
+gem 'sequel', '~> 4.40'
+gem 'sinatra', '>= 2.0.0.beta2', '< 3.0', :require=>'sinatra/base'
+gem 'slim', '~> 3.0'
+gem 'sysrandom', '~> 1.0', :require=>'sysrandom/securerandom'
+
+group :mysql do
+  gem 'jdbc-mysql', '~> 5.1', :platforms=>:jruby, :require=>'jdbc/mysql'
+  gem 'mysql2', '~> 0.4', :platforms=>[:ruby, :mswin]
+end
+
+group :postgresql do
+  gem 'jdbc-postgres', '~> 9.4', :platforms=>:jruby, :require=>'jdbc/postgres'
+  gem 'pg', '~> 0.19', :platforms=>[:ruby, :mswin]
+  gem 'sequel_pg', '~> 1.6', :platforms=>:ruby, :require=>false
+end

+ 35 - 18
frameworks/Ruby/sinatra-sequel/Gemfile.lock

@@ -1,34 +1,51 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    json (1.8.3)
-    mysql2 (0.4.4)
-    puma (2.15.3)
-    rack (1.6.4)
-    rack-protection (1.5.3)
+    jdbc-mysql (5.1.40)
+    jdbc-postgres (9.4.1206)
+    json (2.0.3)
+    json (2.0.3-java)
+    mustermann (1.0.0.beta2)
+    mysql2 (0.4.5)
+    pg (0.19.0)
+    puma (3.6.2)
+    puma (3.6.2-java)
+    rack (2.0.1)
+    rack-protection (2.0.0.beta2)
       rack
-    sequel (4.38.0)
-    sinatra (1.4.7)
-      rack (~> 1.5)
-      rack-protection (~> 1.4)
-      tilt (>= 1.3, < 3)
+    sequel (4.42.1)
+    sequel_pg (1.6.17)
+      pg (>= 0.8.0)
+      sequel (>= 4.0.0)
+    sinatra (2.0.0.beta2)
+      mustermann (= 1.0.0.beta2)
+      rack (~> 2.0)
+      rack-protection (= 2.0.0.beta2)
+      tilt (~> 2.0)
     slim (3.0.7)
       temple (~> 0.7.6)
       tilt (>= 1.3.3, < 2.1)
+    sysrandom (1.0.4)
+    sysrandom (1.0.4-java)
     temple (0.7.7)
     tilt (2.0.5)
 
 PLATFORMS
+  java
   ruby
 
 DEPENDENCIES
-  jdbc-mysql (~> 5.1.38)
-  json (~> 1.8.3)
-  mysql2 (~> 0.4.0)
-  puma (~> 2.15.3)
-  sequel (~> 4.28)
-  sinatra (~> 1.4.6)
-  slim (~> 3.0.6)
+  jdbc-mysql (~> 5.1)
+  jdbc-postgres (~> 9.4)
+  json (~> 2.0)
+  mysql2 (~> 0.4)
+  pg (~> 0.19)
+  puma (~> 3.6)
+  sequel (~> 4.40)
+  sequel_pg (~> 1.6)
+  sinatra (>= 2.0.0.beta2, < 3.0)
+  slim (~> 3.0)
+  sysrandom (= 1.0.4)
 
 BUNDLED WITH
-   1.13.1
+   1.13.7

+ 18 - 11
frameworks/Ruby/sinatra-sequel/README.md

@@ -1,20 +1,27 @@
-# Ruby [Sinatra](http://www.sinatrarb.com/) Benchmarking Test
+# Ruby [Sinatra](http://www.sinatrarb.com)-[Sequel](http://sequel.jeremyevans.net) Benchmarking Test
 
-The information below contains information specific to Sinatra.
-For further guidance, review the
-[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
-Also note the additional information provided in the [Ruby README](../).
+The information below contains information specific to the Sequel rewrite of
+the Sinatra benchmarking test. For further guidance, review the
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).  Also
+note the additional information provided in the [Ruby README](../).
 
 This is the Ruby Sinatra portion of a [benchmarking test suite](../../)
 comparing a variety of web platforms.
 
 ## Infrastructure Software Versions
-The tests were run with:
-* [Ruby 2.2.3](http://www.ruby-lang.org/)
-* [Sinatra 1.4.6](http://www.sinatrarb.com/)
-* [Puma 2.15.3](http://puma.io/)
-* [MySQL 5.5.29](https://dev.mysql.com/)
-* [Sequel 4.28.0](http://sequel.jeremyevans.net/documentation.html)
+
+The tests will be run with:
+
+* [Ruby 2.4](http://www.ruby-lang.org)
+* [JRuby 9.1](http://jruby.org)
+* [Rubinius 3](https://rubinius.com)\*
+* [Puma 3.6](http://puma.io)
+* [Sinatra 2.0](http://www.sinatrarb.com)
+* [Sequel 4.40](http://sequel.jeremyevans.net)
+* [MySQL 5.5](https://www.mysql.com)
+* [Postgres 9.3](https://www.postgresql.org)
+
+\* - Tests are developed but currently disabled due to compatibility issues.
 
 ## Paths & Source for Tests
 

+ 69 - 0
frameworks/Ruby/sinatra-sequel/benchmark_config.json

@@ -23,6 +23,75 @@
       "display_name": "sinatra-sequel-puma-mri",
       "notes": "",
       "versus": "rack-puma-mri"
+    },
+    "postgres": {
+      "setup_file": "run_mri_puma",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "sinatra-sequel",
+      "language": "Ruby",
+      "orm": "Full",
+      "platform": "Rack",
+      "webserver": "Puma",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "sinatra-sequel-postgres-puma-mri",
+      "notes": "",
+      "versus": "rack-puma-mri"
+    },
+    "puma-jruby": {
+      "setup_file": "run_jruby_puma",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "sinatra-sequel",
+      "language": "Ruby",
+      "orm": "Full",
+      "platform": "JRuby",
+      "webserver": "Puma",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "sinatra-sequel-puma-jruby",
+      "notes": "",
+      "versus": "sinatra-sequel-puma-mri"
+    },
+    "postgres-puma-jruby": {
+      "setup_file": "run_jruby_puma",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "sinatra-sequel",
+      "language": "Ruby",
+      "orm": "Full",
+      "platform": "JRuby",
+      "webserver": "Puma",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "sinatra-sequel-postgres-puma-jruby",
+      "notes": "",
+      "versus": "sinatra-sequel-postgres-puma-mri"
     }
   }]
 }

+ 1 - 0
frameworks/Ruby/sinatra-sequel/config.ru

@@ -1,2 +1,3 @@
+# frozen_string_literal: true
 require_relative 'hello_world'
 run HelloWorld

+ 26 - 0
frameworks/Ruby/sinatra-sequel/config/mri_puma.rb

@@ -0,0 +1,26 @@
+# Enable Puma's clustered mode with about one process per 128 MiB of available
+# memory, scaling up to as close to MAX_THREADS as possible. If there are fewer
+# processes than MAX_THREADS, add threads per process to reach MAX_THREADS.
+RESERVE_KB = 262_144
+KB_PER_WORKER = 131_072 # average of peak PSS of puma processes (watch smem -U testrunner -k)
+MIN_WORKERS = 2
+MIN_THREADS_PER_WORKER = 4
+MAX_THREADS = (ENV['MAX_CONCURRENCY'] || 256).to_i
+
+def meminfo(arg)
+  File.open('/proc/meminfo') do |f|
+    f.each_line do |line|
+      key, value = line.split(/:\s+/)
+      return value.split(/\s+/).first.to_i if key == arg
+    end
+  end
+end
+
+# FWBM only... use puma_auto_tune in production!
+avail_mem = meminfo('MemAvailable') - RESERVE_KB
+num_workers = [[avail_mem / KB_PER_WORKER, MIN_WORKERS].max, MAX_THREADS].min
+num_threads = num_workers < MAX_THREADS ? (1.0 * MAX_THREADS / num_workers).ceil : 0
+num_threads = [num_threads, MIN_THREADS_PER_WORKER].max
+
+workers num_workers
+threads num_threads, num_threads

+ 79 - 53
frameworks/Ruby/sinatra-sequel/hello_world.rb

@@ -1,24 +1,39 @@
+# frozen_string_literal: true
+require 'time'
+
 MAX_PK = 10_000
+QUERIES_MIN = 1
+QUERIES_MAX = 500
 SEQUEL_NO_ASSOCIATIONS = true
 
-Bundler.require :default
-
-# Configure Sequel ORM (Sequel::DATABASES)
-Sequel.connect \
-  '%<adapter>s://%<host>s/%<database>s?user=%<user>s&password=%<password>s' % {
-    :adapter => RUBY_PLATFORM == 'java' ? 'jdbc:mysql' : 'mysql2',
-    :host => ENV['DBHOST'],
-    :database => 'hello_world',
-    :user => 'benchmarkdbuser',
-    :password => 'benchmarkdbpass'
-  },
-  :max_connections => (ENV['MAX_THREADS'] || 4).to_i,
-  :pool_timeout => 5
+Bundler.require(:default) # Load core modules
+
+def connect(dbtype)
+  Bundler.require(dbtype) # Load database-specific modules
+
+  adapters = {
+    :mysql=>{ :jruby=>'jdbc:mysql', :mri=>'mysql2' },
+    :postgresql=>{ :jruby=>'jdbc:postgresql', :mri=>'postgres' }
+  }
+
+  Sequel.connect \
+    '%<adapter>s://%<host>s/%<database>s?user=%<user>s&password=%<password>s' % {
+      :adapter=>adapters.fetch(dbtype).fetch(defined?(JRUBY_VERSION) ? :jruby : :mri),
+      :host=>ENV.fetch('DBHOST', '127.0.0.1'),
+      :database=>'hello_world',
+      :user=>'benchmarkdbuser',
+      :password=>'benchmarkdbpass'
+    },
+    :max_connections=>Puma.cli_config.options.fetch(:max_threads),
+    :pool_timeout=>10
+end
 
-# Allow #to_json on models and datasets
-Sequel::Model.plugin :json_serializer
+DB = connect ENV.fetch('DBTYPE').to_sym
 
-class World < Sequel::Model(:World); end
+# Define ORM models
+class World < Sequel::Model(:World)
+  def_column_alias(:randomnumber, :randomNumber) if DB.database_type == :mysql
+end
 
 class Fortune < Sequel::Model(:Fortune)
   # Allow setting id to zero (0) per benchmark requirements
@@ -27,8 +42,8 @@ end
 
 # Configure Slim templating engine
 Slim::Engine.set_options \
-  :format => :html,
-  :sort_attrs => false
+  :format=>:html,
+  :sort_attrs=>false
 
 # Our Rack application to be executed by rackup
 class HelloWorld < Sinatra::Base
@@ -40,14 +55,26 @@ class HelloWorld < Sinatra::Base
     # XSS, CSRF, IP spoofing, etc. protection are not explicitly required
     disable :protection
 
-    # Only add ;charset= to specific content types per the benchmark requirements
-    set :add_charset, %w[text/html]
+    # Only add the charset parameter to specific content types per the requirements
+    set :add_charset, [mime_type(:html)]
   end
 
   helpers do
+    def bounded_queries
+      queries = params[:queries].to_i
+      return QUERIES_MIN if queries < QUERIES_MIN
+      return QUERIES_MAX if queries > QUERIES_MAX
+      queries
+    end
+
+    def json(data)
+      content_type :json
+      JSON.fast_generate(data)
+    end
+
     # Return a random number between 1 and MAX_PK
     def rand1
-      Random.rand(MAX_PK) + 1
+      Random.rand(MAX_PK).succ
     end
 
     # Return an array of `n' unique random numbers between 1 and MAX_PK
@@ -58,60 +85,59 @@ class HelloWorld < Sinatra::Base
 
   after do
     # Add mandatory HTTP headers to every response
-    response['Server'] ||= 'Puma'.freeze
-    response['Date'] ||= Time.now.to_s
-  end
-
-  get '/json', :provides => :json do
-    JSON.fast_generate :message => 'Hello, World!'.freeze
+    response['Server'] ||= Puma::Const::PUMA_SERVER_STRING
+    response['Date'] ||= Time.now.httpdate
   end
 
-  get '/plaintext', :provides => :text do
-    'Hello, World!'.freeze
+  # Test type 1: JSON serialization
+  get '/json' do
+     json :message=>'Hello, World!'
   end
 
-  get '/db', :provides => :json do
-    World[rand1].to_json
+  # Test type 2: Single database query
+  get '/db' do
+    json World[rand1].values
   end
 
-  get '/queries', :provides => :json do
-    queries = (params[:queries] || 1).to_i
-    queries = 1 if queries < 1
-    queries = 500 if queries > 500
-
+  # Test type 3: Multiple database queries
+  get '/queries' do
     # Benchmark requirements explicitly forbid a WHERE..IN here, so be good
-    worlds = randn(queries).map! { |id| World[id] }
+    worlds = randn(bounded_queries).map! { |id| World[id] }
 
-    World.to_json :array => worlds
+    json worlds.map!(&:values)
   end
 
+  # Test type 4: Fortunes
   get '/fortunes' do
     @fortunes = Fortune.all
     @fortunes << Fortune.new(
-      :id => 0,
-      :message => 'Additional fortune added at request time.'.freeze
+      :id=>0,
+      :message=>'Additional fortune added at request time.'
     )
     @fortunes.sort_by!(&:message)
 
     slim :fortunes
   end
 
-  get '/updates', :provides => :json do
-    queries = (params[:queries] || 1).to_i
-    queries = 1 if queries < 1
-    queries = 500 if queries > 500
-
-    # Benchmark requirements explicitly forbid a WHERE..IN here, and specify
-    # that each transaction only read and write a single record, so be good
-    worlds = []
-    randn(queries).each do |id|
-      World.db.transaction do
+  # Test type 5: Database updates
+  get '/updates' do
+    # Benchmark requirements explicitly forbid a WHERE..IN here, transactions
+    # are optional, batch updates are allowed (but each transaction can only
+    # read and write a single record?), so... be good
+    worlds = randn(bounded_queries).map! do |id|
+      DB.transaction do
         world = World.for_update[id]
-        world.update :randomNumber => rand1
-        worlds << world
+        world.update :randomnumber=>rand1
+        world
       end
     end
 
-    World.to_json :array => worlds
+    json worlds.map!(&:values)
+  end
+
+  # Test type 6: Plaintext
+  get '/plaintext' do
+    content_type :text
+    'Hello, World!'
   end
 end

+ 18 - 0
frameworks/Ruby/sinatra-sequel/run_jruby_puma.sh

@@ -0,0 +1,18 @@
+#!/bin/bash
+
+if [[ $LOGDIR == *postgres* ]] ; then
+  DBTYPE=postgresql
+else
+  DBTYPE=mysql
+fi
+
+fw_depends $DBTYPE rvm jruby-9.1
+
+rvm jruby-$JRUBY_VERSION do \
+  bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
+
+export DBTYPE
+export JRUBY_OPTS="-J-Xmn512m -J-Xms2048m -J-Xmx2048m -J-server -J-XX:+UseSerialGC -J-Djava.net.preferIPv4Stack=true"
+
+rvm jruby-$JRUBY_VERSION do \
+  bundle exec puma -t $MAX_CONCURRENCY:$MAX_CONCURRENCY -b tcp://0.0.0.0:8080 -e production &

+ 10 - 10
frameworks/Ruby/sinatra-sequel/run_mri_puma.sh

@@ -1,18 +1,18 @@
 #!/bin/bash
 
-fw_depends mysql rvm ruby-2.2
+if [[ $LOGDIR == *postgres* ]] ; then
+  DBTYPE=postgresql
+else
+  DBTYPE=mysql
+fi
+
+fw_depends $DBTYPE rvm ruby-2.4
 
 rvm ruby-$MRI_VERSION do \
   bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
 
-# Enable Puma's clustered mode with about one process per hardware thread,
-# scaling up to a maximum of about 256 concurrent threads. NOTE: I was having
-# trouble keeping two cores saturated with only two workers, thus the "fuzzy"
-# math here.
-
-WORKERS=$(( $(nproc || echo 7) + 1 ))
-MAX_THREADS=$(( 256 / WORKERS + 1 )) ; export MAX_THREADS
-MIN_THREADS=$(( MAX_THREADS / 4 + 1 ))
+export DBTYPE
+export MAX_CONCURRENCY # used by config/mri_puma.rb
 
 rvm ruby-$MRI_VERSION do \
-  bundle exec puma -w $WORKERS -t $MIN_THREADS:$MAX_THREADS -b tcp://0.0.0.0:8080 -e production &
+  bundle exec puma -C config/mri_puma.rb -b tcp://0.0.0.0:8080 -e production &

+ 7 - 7
toolset/setup/linux/languages/ruby/jruby-1.7.sh

@@ -2,16 +2,16 @@
 
 fw_depends rvm java
 
+fw_installed jruby-1.7 && return 0
+
 # rvm stable [typically] only provides one version of jruby-1.7
 # update this when it changes
-JRUBY_VERSION="1.7.9"
-
-fw_installed jruby-$JRUBY_VERSION && return 0
+JRUBY_VERSION="1.7.26"
 
 rvm install jruby-$JRUBY_VERSION
-# Bundler is SOMETIMES missing... not sure why.
-rvm jruby-$JRUBY_VERSION do gem install bundler
+# Use a specific version of Bundler to work around thread concurrency issues.
+rvm jruby-$JRUBY_VERSION do gem install bundler -v 1.13.7
 
-echo "export JRUBY_VERSION=${JRUBY_VERSION}" > $IROOT/jruby-$JRUBY_VERSION.installed
+echo "export JRUBY_VERSION=${JRUBY_VERSION}" > $IROOT/jruby-1.7.installed
 
-source $IROOT/jruby-$JRUBY_VERSION.installed
+source $IROOT/jruby-1.7.installed

+ 17 - 0
toolset/setup/linux/languages/ruby/jruby-9.0.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+fw_depends rvm java
+
+fw_installed jruby-9.0 && return 0
+
+# rvm stable [typically] only provides one version of jruby-9.0
+# update this when it changes
+JRUBY_VERSION="9.0.5.0"
+
+rvm install jruby-$JRUBY_VERSION
+# Use a specific version of Bundler to work around thread concurrency issues.
+rvm jruby-$JRUBY_VERSION do gem install bundler -v 1.13.7
+
+echo "export JRUBY_VERSION=${JRUBY_VERSION}" > $IROOT/jruby-9.0.installed
+
+source $IROOT/jruby-9.0.installed

+ 17 - 0
toolset/setup/linux/languages/ruby/jruby-9.1.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+fw_depends rvm java
+
+fw_installed jruby-9.1 && return 0
+
+# rvm stable [typically] only provides one version of jruby-9.0
+# update this when it changes
+JRUBY_VERSION="9.1.7.0"
+
+rvm install jruby-$JRUBY_VERSION
+# Use a specific version of Bundler to work around thread concurrency issues.
+rvm jruby-$JRUBY_VERSION do gem install bundler -v 1.13.7
+
+echo "export JRUBY_VERSION=${JRUBY_VERSION}" > $IROOT/jruby-9.1.installed
+
+source $IROOT/jruby-9.1.installed

+ 0 - 27
toolset/setup/linux/languages/ruby/jruby-9k.sh

@@ -1,27 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm java
-
-fw_installed jruby-9k && return 0
-
-# rvm stable [typically] only provides one version of jruby-9.0
-# update this when it changes
-JRUBY_VERSION="9.0.0.0.pre1"
-
-# We assume single-user installation as
-# done in our rvm.sh script and
-# in Travis-CI
-if [ "$TRAVIS" = "true" ]
-then
-  rvmsudo rvm install jruby-$JRUBY_VERSION
-  # Bundler is SOMETIMES missing... not sure why.
-  rvmsudo rvm jruby-$JRUBY_VERSION do gem install bundler
-else
-  rvm install jruby-$JRUBY_VERSION
-  # Bundler is SOMETIMES missing... not sure why.
-  rvm jruby-$JRUBY_VERSION do gem install bundler
-fi
-
-echo "export JRUBY_VERSION=${JRUBY_VERSION}" > $IROOT/jruby-9k.installed
-
-source $IROOT/jruby-9k.installed

+ 2 - 2
toolset/setup/linux/languages/ruby/ruby-2.0.sh

@@ -6,11 +6,11 @@ fw_installed ruby-2.0 && return 0
 
 # rvm stable [typically] only provides one version of ruby-2.0
 # update this when it changes
-MRI_VERSION=2.0.0-p643
+MRI_VERSION=2.0.0-p648
 
 rvm install $MRI_VERSION
 # Bundler is SOMETIMES missing... not sure why.
-rvm $MRI_VERSION do gem install bundler
+rvm $MRI_VERSION do gem install bundler -v 1.13.7
 
 echo "export MRI_VERSION=${MRI_VERSION}" > $IROOT/ruby-2.0.installed
 

+ 2 - 2
toolset/setup/linux/languages/ruby/ruby-2.1.sh

@@ -6,11 +6,11 @@ fw_installed ruby-2.1 && return 0
 
 # rvm stable [typically] only provides one version of ruby-2.1
 # update this when it changes
-MRI_VERSION=2.1.5
+MRI_VERSION=2.1.10
 
 rvm install $MRI_VERSION
 # Bundler is SOMETIMES missing... not sure why.
-rvm $MRI_VERSION do gem install bundler
+rvm $MRI_VERSION do gem install bundler -v 1.13.7
 
 echo "export MRI_VERSION=${MRI_VERSION}" > $IROOT/ruby-2.1.installed
 

+ 2 - 2
toolset/setup/linux/languages/ruby/ruby-2.2.sh

@@ -6,11 +6,11 @@ fw_installed ruby-2.2 && return 0
 
 # rvm stable [typically] only provides one version of ruby-2.2
 # update this when it changes
-MRI_VERSION=2.2.2
+MRI_VERSION=2.2.6
 
 rvm install $MRI_VERSION
 # Bundler is SOMETIMES missing... not sure why.
-rvm $MRI_VERSION do gem install bundler
+rvm $MRI_VERSION do gem install bundler -v 1.13.7
 
 echo "export MRI_VERSION=${MRI_VERSION}" > $IROOT/ruby-2.2.installed
 

+ 17 - 0
toolset/setup/linux/languages/ruby/ruby-2.4.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+fw_depends llvm-dev rvm
+
+fw_installed ruby-2.4 && return 0
+
+# rvm stable [typically] only provides one version of ruby-2.4
+# update this when it changes
+MRI_VERSION=2.4.0
+
+rvm install $MRI_VERSION
+# Bundler is SOMETIMES missing... not sure why.
+rvm $MRI_VERSION do gem install bundler -v 1.13.7
+
+echo "export MRI_VERSION=${MRI_VERSION}" > $IROOT/ruby-2.4.installed
+
+source $IROOT/ruby-2.4.installed