Recently we worked with a client where we had to run a part of their multi-threaded code in JRuby for performance reasons. They have been using CircleCI with MRI for running tests. In this post I will explain how we configured CircleCI to run the same tests using both JRuby and MRI.
CircleCI uses circle.yml file for configuration. Before configuring JRuby, this is how it looked like:
1machine: 2 ruby: 3 version: 2.1.5 4 5dependencies: 6 pre: 7 - ./bundle_install_circle_ci.sh 8 cache_directories: 9 - "~/vendor/bundle" 10 11test: 12 override: 13 - ? bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app.xml 14 : parallel: true 15 pwd: app 16 files: 17 - spec/**/*_spec.rb
Specify the JDK version
We need to specify a JDK version before using JRuby.
1machine: 2 java: 3 version: openjdk7
Install proper dependencies
We needed to use JRuby 9.0.4.0 but the version of JRuby that came with Ubuntu 12.04 image of CircleCI was different. We added rvm install command as follows to install specific version that we wanted. Also we can configure any script (like bundle install) that needs to run before running tests.
1dependencies: 2 pre: 3 - rvm install jruby-9.0.4.0 4 - ./bundle_install_jruby_circle_ci.sh 5 6 cache_directories: 7 - "~/vendor/bundle"
Configure JRuby
We used rvm-exec to set JRuby for running tests for this particular component in the test section. Otherwise by default it picks up MRI.
1test: 2 override: 3 - ? rvm-exec jruby-9.0.4.0 bash -c "bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_jruby.xml" 4 : parallel: true 5 pwd: app 6 files: 7 - spec/**/*_spec.rb
Improving test runs on JRuby
Once we started running tests with JRuby, we observed it was taking comparatively slower to finish all tests. Most of the time was spent in starting the JVM. We made it faster by setting --dev parameter in JRUBY_OPTS environment variable. This parameter improves JRuby boot time and it shaved more than a minute time for us.
1machine: 2 environment: 3 JRUBY_OPTS: "--dev"
Here is the final circle.yml file:
1# circle.yml 2 3machine: 4 ruby: 5 version: 2.1.5 6 7 java: 8 version: openjdk7 9 10 environment: 11 JRUBY_OPTS: "--dev" 12 13dependencies: 14 pre: 15 - rvm install jruby-9.0.4.0 16 - ./bundle_install_jruby_circle_ci.sh 17 18 cache_directories: 19 - "~/vendor/bundle" 20 21test: 22 override: 23 - ? rvm-exec jruby-9.0.4.0 bash -c "bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_jruby.xml" 24 : parallel: true 25 pwd: app 26 files: 27 - spec/**/*_spec.rb 28 29 - ? bundle exec rspec --format progress --format documentation --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/app_mri.xml 30 : parallel: true 31 pwd: app 32 files: 33 - spec/**/*_spec.rb