How to improve jRuby load time? - ruby

I have to wait quite long time (comparing to my friends machines) for executing scripts on jRuby, especially when I'm running rake tasks or tests. I've tried jRuby version 1.3.1 and 1.4.1 with and without ruby-debug gem and the same problem occurred in each configuration.
The question is simple:
Is there any way to improve jRuby load process?
..or have I something wrong with my jvm configuration or jRuby installation (I'm using jRuby via rvm - ruby version manager)?

There are a couple of things you could try:
use the very latest and greatest version of JRuby (due to the extensive testsuites, even the bleeding edge git master branch is usually pretty stable), they are constantly working on startup time
choose your JVM wisely, Oracle JRockit for example is geared towards servers and thus startup performance is not a concern (those apps are only restarted once every couple of years anyway), Sun has mainly neglected the desktop for the last ten years or so, but has gotten consistently better since 1.6u12 (try the recently released 1.6u18) and also in 1.7. IBM's J9 is also said to be pretty lightweight.
try nailgun, which is a project that keeps a JVM running as a daemon in the background (there is builtin support in JRuby, try running your scripts with jruby --ng)
just don't use JRuby for unit tests and rake tasks: the ThoughtWorks Mingle team, for example uses MRI for unit tests, rake tasks and development and JRuby for integration tests, regression tests and production. (This obviously only works if you don't use any Java libraries in your rake tasks and tests.)
However, tests and scripts are the worst case scenario for JRuby. The JRuby runtime alone is already pretty heavy, much heavier than MRI. Just loading the entire beast from disk into RAM can already take longer than running the same script in MRI. And we haven't even added the startup time for the JVM yet!

Also, make sure that you run JVM in client mode (assuming that you're using Sun's JVM), since this mode provides faster startup and better overall performance for things like test suites. JRuby by default should use JVM in client mode, but this depends on the system and your JVM settings, etc. To verify that you're using client JVM, invoke jruby -v and you should see something like this
Java HotSpot(TM) *Client* VM 1.6.0_18
Update: Take a look at Charles' blog post with tips to improve startup: http://blog.headius.com/2010/03/jruby-startup-time-tips.html

JRuby now has a --dev flag which combines many speedy options. I ran my model tests on Rails 5 and JRuby 9.1.7.0 with over 80% improvement!
$ time rspec spec/models
Finished in 2.85 seconds (files took 10.63 seconds to load)
86 examples, 0 failures
rspec spec/models 57.79s user 1.14s system 288% cpu 20.425 total
$ time JRUBY_OPTS=--dev rspec spec/models
Finished in 1.4 seconds (files took 4.15 seconds to load)
86 examples, 0 failures
JRUBY_OPTS=--dev rspec spec/models 11.51s user 0.48s system 139% cpu 8.600 total
Don't want to type all of this? Create a Makefile! You can add -G to include bundle exec
# Makefile
tests:
JRUBY_OPTS='--dev -G' rspec
Then simply run
$ make tests
source: https://github.com/jruby/jruby/wiki/Improving-startup-time

spork might help, if its unit tests you want to improve time on.

Related

Ruby.exe only using 25% CPU resources

When trying to run an intensive Ruby method, I noticed it's only using 25% of the CPU resources while 70% sits idle. Is there any way to configure this to use more? I'm on Windows 7, ruby 2.0.0
You probably have 4 CPU cores. You're running 1 Ruby process. 1 Ruby process = 1 thread = can use max 1 CPU core. The MRI (default) implementation of Ruby currently cannot run more than 1 thread in parallel. For that, you may want to try JRuby or some other implementation like Rubinius that allows parallel threads. I'm guessing you'll need to learn a bit about multi-threading to understand this wholly, start by reading some basic tutorials and then questions like "Does ruby have real multithreading?".
When the process is running, go to the task manager, right click on the program, click "go to process," right click on the process, go to select priority, and check off "high."
Important: never set application to "realtime" it may cause several problems.
references:
http://www.tomshardware.com/forum/57576-63-maximum-capacity-application

Running same Cucumber Features on different machines concurrently using parallel_tests gem

Running same Cucumber Features on different machines concurrently using parallel_tests gem
I'm trying to figure out how to use the parallel_tests gem to run the EXACT SAME Cucumber Features on a variety of different machines concurrently.
Currently I have them running on different machines but the SAME features do not execute, it just splits up the features and runs different features on different machines.
More clarification on what I want to do:
MACHINE 1 (Win 7) - EXECUTE SAME FEATURES CONCURRENTLY
MACHINE 2 (Win 8) - EXECUTE SAME FEATURES CONCURRENTLY
MACHINE 3 (Mac OS X) - EXECUTE SAME FEATURES CONCURRENTLY
...
Also my architecture is:
Cucumber -> Capybara -> Selenium Webdriver -> Selenium Grid
parallel_tests gem: https://github.com/grosser/parallel_tests
The parallel_tests gem is really purposed to parallellism, not executing multiple platforms.
You may find the following useful:
Sauce Gem 30 rake tasks
"The Sauce integration is currently targeted at RSpec and Cucumber, running on a local server you can spin up multiple copies of. It runs a copy of each test for each platform, and divides them up across all the concurrency available to your Sauce Labs account by default"
Hope it helps, I haven't used it myself yet.
Thanks for the clarification. To accomplish testing your app for all the supported environments (OSs/browsers) you can use something as Selenium Grid here is an example Selenium RC: Run tests in multiple browsers automatically.
TestingBot is a service that use this: http://blog.testingbot.com/2012/02/19/selenium-cucumber-capybara
Other approach is described here: http://altoros.github.io/2013/running-capybara-tests-in-remote-browsers/
http://paauspaani.blogspot.mx/2013/05/running-tests-remotely-using-selenium.html
There is also a presentation: http://www.slideshare.net/martinkleppmann/crossbrowser-testing-in-the-real-world
Also this could help you Has anyone figured out a way to run the same cucumber scenario on multiple browsers/web drivers?
Hopefully this will give you some clues.
I am confused by this statement of yours:
Currently I have them running on different machines but the SAME
features do not execute, it just splits up the features and runs
different features on different machines.
parallel_tests is used for splitting up tests and running them on multiple cores, not on a distributed environment of multiple machines. It can group tests to be run on a distributed environment using the --only-group flag, but it doesn't actually run tests on a distributed environment. So you have to do some lifting yourself to get the tests running on a distributed environment. You could run all of your tests on multiple machines like so:
Use net-ssh to ssh into each one of your boxes.
Use each ssh session to run your parallel_tests script (which should break the tests up and run them in parallel on the current box -- just don't use the --only-group option as described here)

Rake tests running very slow

After running some tests, I'm convinced there has to be something wrong with my setup (windows, rubymine and latest ruby versions). My times right now are:
Finished tests in 14.289817s, 0.0700 tests/s, 0.3499 assertions/s.
1 tests, 5 assertions, 0 failures, 0 errors, 0 skips
Process finished with exit code 0
With 5 VERY easy tests (just checking if validation on empty fields works). The total time for these 5 unit tests is 160 seconds, over 2 minutes.
What could I do to improve this speed?
Here are the tests:
require 'test_helper'
class ItemTest < ActiveSupport::TestCase
test 'item attributes must not be empty' do
item = Item.new
assert item.invalid?
assert item.errors[:name].any?
assert item.errors[:description].any?
assert item.errors[:image_url].any?
assert item.errors[:rating].any?
end
end
Your problem is Windows. We use JRuby on Windows and it actually runs faster than RubyInstaller(mingw) ruby on Windows but we do see very slow results when running test suites or starting a rails server. About 1 minute for a single test run due to the loading of the Rails environment.
You have a few options:
Switch to linux / osx
Use spork to keep a couple rails environments pre-loaded for your tests. Note that this isn't perfect but it will reduce your times substantially. With this option you'll probably want to use minitest or rspec, I had trouble getting spork to work on Windows with testunit. With spork you should be able to get your single test run time down to about 10 seconds.
Write as many of your tests to run outside of Rails, in other words to not require the Rails stack. This will be very fast, you should be able to run a test in only a few seconds but as you could guess, it's hard to test a lot of things (controllers, views) outside of rails. Works perfectly though for functions you've broken out into modules that already do not require anything from rails.
Good luck!
What's the rest of your gem stack? Sometimes third-party gems are initialized by rails and will try to phone home (New Relic, Airbrake) which can inflate your test times (though probably not by this much). If something isn't strictly required for your test suite, you should try to pull it into the proper env group, or set require :false via bundler:
group :production do
gem 'newrelic_rpm'
end
Startup time appears to be killing you, so you and I are probably in the same boat. Between Jodell and Dark Castle a lot of this is covered already, but here's my nearly-whole list of things that helped, in descending order of efficacy.
Get a patched 1.9.3 with the 2.0 filesystem improvements backported. The first gets 2x better numbers but I'm using the second because I felt the first was unstable
https://groups.google.com/forum/?fromgroups=#!topic/thecodeshop/WVA4N2lJoM4
https://raw.github.com/gist/3242245/5cdb932c0a544cfbb51fdee5759942d4d2c263f5/1-complete.diff
Set your GC options
http://snaprails.tumblr.com/post/241746095/rubys-gc-configuration (I'm using the last one)
Turn off collecting coverage data (My IDE kept volunteering this)
Run Spork, and set SPEC_OPTS=--drb
Turn off virus scanner (don't actually do this, it's only worth 10% for me anyway)
Double-check your Gems, delaying the loading of gems with require: false
6 didn't actually buy me very much. The biggest thing we had wrong was loading Thin unconditionally (which pulls in Eventmachine, which 21 megabytes installed), but the next 3 on the stack were actually being used by RSpec. I have not looked at network traffic, but Jodell is probably on to something there.

Huge memory leak / bloat after Upgrading from Rails 3.0 to Rails 3.2 (Ruby 1.9.3 + Passenger)

Last week we upgraded a small project which was running on Rails 3.0.1 to Rails 3.2.2.
Shortly after the upgrade we recognized that occasionally, 2-3 times a day, we're seening a huge Phusion Passenger process (1-5 GB).
We're running Phusion Passenger 3.0.11 and Ruby 1.9.3-p0. We already tried different Ruby version (1.9.2-p290 and 1.9.3-p125) without a success.
Afterwards, we tried to track our memory usage with Oink. Unfortunately Oink doesn't show the reason for the memory bloat - The large processes seem to not write to the logfiles anymore.
When we downgraded back to Rails 3.0.1 the problem is gone. Does anyone have similar problems? We really checked our code for possible memory leaks, such as too many ActiveRecord instances, but didn't find any.
Do you think it's worth it to try Unicorn instead of Passenger? Or is it likely that we'll run into the same problem?
Any suggestions about how to trace the memory leak are welcome. We already set up newrelic, but it doesn't show detailed information about the memory leak.
If this is Red Hat compatible Linux, you can use SystemTap. I am not sure if SystemTap is available on Debian/Ubuntu systems, if not there is alternative called DTrace. Here are some articles - I have been pretty successful with tracking down several regressions, although none of these were memory issues (maybe you can find a STP script that could do the trick for you). Read here:
http://lukas.zapletalovi.com/2012/02/peek-into-your-ruby-app-with-systemtap.html
http://lukas.zapletalovi.com/2012/01/probing-ruby-apps-with-systemtap-in.html
http://sourceware.org/systemtap/wiki/RubyMarker
The last link shows probes you can hoop into in SystemTaps in Ruby. There are thinks like gc runs or memory allocations, could help you. Good luck!
I would be interested to know what passenger-memory-stats shows and what type of Memory you have passenger set for PassengerMaxPoolSize PassengerPoolIdleTime and any other passenger settings.
How did you upgrade passenger?
What is your apache setup like? prefork or worker?
I suspect that you are seeing poor gc performance, attempt to tune them by putting this in a wrapper around the ruby that passenger uses:
#!/bin/sh
export RUBY_HEAP_MIN_SLOTS=600000
export RUBY_GC_MALLOC_LIMIT=59000000
export RUBY_FREE_MIN=200000
exec "/usr/bin/ruby" "$#"
It should fix some performance issues you are seeing in general due to poor ruby gc defaults.

rspec tests under jruby on Windows running very slow

We are considering a move to jruby, and as part of this have been researching testing approaches and frameworks. I've been testing rspec on my local development machine and am finding that the total time taken to run 2 tests for a single class with 2 very simple methods is 7-8 seconds. By simple, I mean one setter and one that returns true.
The rspec output shows that the tests run in roughly 2 seconds, so 5-6 seconds of the total time is spent loading and initializing rspec. I'm running from the command line using
C:\rubycode\rspec_tutorial>rspec --profile user_spec.rb
..
Top 2 slowest examples:
User User should NOT be in any roles not assigned to it
0.023 seconds ./user_spec.rb:15
User User should be in any roles assigned to it
0.006 seconds ./user_spec.rb:10
Finished in 2 seconds
2 examples, 0 failures
I'm running jruby 1.6.5 and rspec 2.7.1
I've read this post, Faster RSpec with JRuby
but it's over 1.5 years old, and the answer relates to running suites of tests as opposed to short bursts of a small number of tests locally to aid TDD, which is how we want to develop. Down the line we'll incorporate a CI server.
My question is, is this the expected execution time? Is there any way to speed up the running of rspec tests on the local development machine uner JRUBY?
EDIT:
Biggest performance gains were switching from 64 bit "server" JVM to 32 bit "client" mode. I saw about a 40% reduction in the time taken to run a simple test. I got Nailgun up and running as well, but performance varied. The link provided below by banzaiman was most helpful
It is not loading RSpec, but it is JVM startup time you are feeling.
See https://github.com/jruby/jruby/wiki/Improving-startup-time for more information.

Resources