The default configuration for running JRuby on Rails using GoldSpike only allows 4 instances of the JRuby runtime. This means that if there are more than 4 simultaneous requests from clients, the web server will respond with a server overloaded error. The easiest way to see what’s going on is to take a look at the ‘createObjectPool’ method of RailsServlet.
With a dedicated production server with 1gig of memory, it is possible to allow a lot more JRuby runtimes, and hence allow for more simultaneous users. A little load testing on a fairly small app suggested that 20 instances of JRuby runtime would fit comfortably under the 1gig ceiling and not overload the processor.
An easy way to change the max number of runtimes is to edit ‘web.xml’ in a JRuby application’s WEB-INF directory. Parameter is set as follows:
<context-param> <param-name>jruby.pool.maxActive</param-name> <param-value>20</param-value> </context-param>
It is also worth checking with the web server configuration to ensure that the web server allows more threads than the number of JRuby runtimes specified in ‘web.xml’.
Say you wanted to store some information across different calls to your JRuby/Rails application on the server side. You could use a database, or memcached. However, what if you just want to do something very simple like a basic cache, and you don’t have a database for your application? Memcached seems like overkill, and would complicate your deployment considerably. So, what about just using statics?
Well, you can’t do it in Ruby, as the Rails integration servlet spawns multiple instances of the JRuby interpreter.
Ruby code in a page view:
<h1>Ruby global number</h1> <% $i ||= 0 %> <% $i += 1 %> <%= $i %> <h1>Ruby obj id</h1> <% $o ||= Object.new %> <%= $o.object_id %>
Results between multiple refreshes of the page:
Ruby global number 1 Ruby obj id 244 Ruby global number 1 Ruby obj id 256 Ruby global number 2 Ruby obj id 244 Ruby global number 2 Ruby obj id 256
Our requests seem to be switching between two instances of the Ruby interpreter.
However, we *can* do it in Java. My clever, Java-literate colleagues explained that Java application servers and servlet containers use a single instance of the JVM, but have a class loader for each application. The class loader stores class information and static values. This means that within one application, the static values will be maintained between requests, but a different application on the same server will have its own set of unrelated static values (similar to AppDomains in .NET).
If we add a call to a static method in Java that increments an integer and returns it, our view looks like this:
<h1>Ruby global number</h1> <% $i ||= 0 %> <% $i += 1 %> <%= $i %> <h1>Ruby obj id</h1> <% $o ||= Object.new %> <%= $o.object_id %> <h1>Java incrementing static integer</h1> <%= TestClass.incrementAndReturnNumber() %>
Our results now look a lot more useful. The Java static integer is getting incremented each call to the view:
Ruby global number 1 Ruby obj id 244 Java number 1 Ruby global number 1 Ruby obj id 256 Java number 2 Ruby global number 2 Ruby obj id 244 Java number 3 Ruby global number 2 Ruby obj id 256 Java number 4
From this little experiment, Java statics seem like a possible way to go for storing temporary data on the server side (eg, a cache implemented as a singleton) for JRuby / Rails. Another option may be to use the ServletContext from the JRuby Rails integration servlet – probably an area worth investigating.
Here’s what I’ve been able to find.
Which technologies have the most demand for people?
From Indeed.com, which claims to search “millions of jobs from thousands of job sites”, but I suspect may have a USA focus:
Here’s job counts from the (largest?) primarily Australian job search site Seek on 5 June 2007, 3pm (today):
|Keyword(s)||Number of positions found|
|“.NET” or “dot net”||2,744|
|“c#” or “c sharp”||1,722|
As an aside, I remember doing a search on Seek for “ruby” about 6 months ago, and getting under 20 jobs mentioning it.
Search Engine Number of Hits
Extract from the TIOBE Programming Community Index for June 2007:
|Delta in Position||Programming Language||Ratings
The data collected suggests that:
- Both .NET and Java are major players in the job market with thousands of positions advertised, implying wide industry adoption of both.
- Neither .NET nor Java seem to be undergoing any significant decline in jobs.
- Java has much more information about it on the internet, although .NET is slowing gaining ground and Java slowly losing it.
- Ruby is comparatively tiny but growing rapidly in terms of jobs and information on the internet.
Recently got a JRuby/Rails system with Java integration up and running. Unfortunately, it took quite a few hours, as most of the docs and code you find through Google are out of date.
If you use JRuby 0.9.2 from Codehaus, you will get an error similar to this when you try to access a rails application:
[2007-02-26 17:54:59] INFO WEBrick::HTTPServer start: pid=22540508 port=3000
<ArgumentError: Anonymous modules have no name to be referenced by>
If you’re stuck in this rut, fear not! Nick Sieger has written very helpful instructions which outline how to get and set up the latest development snapshot. Please note that in addition to the instructions, you need to set your JRUBY_HOME environment variable. Under Windows, do something like this:
If you’d prefer not to use the snapshot, you can get the source code through subversion from:
but at the time of this post, you need to run svn checkout or update with “–ignore-externals” to avoid the following error:
Error: URL ‘svn://rubyforge.org/var/svn/bfts/bfts/trunk’ doesn’t exist
I was reading through some code the other day and was surprised to find that it was using doubles to represent dollar amounts. Reason for the alarm bells is that doubles and floats cannot accurately represent many decimal fractions (eg, 0.1), since doubles and floats internally work with powers of 2 rather than powers of 10. These inaccuracies are likely to lead to significant errors, especially when performing arithmetic (eg, adding up a table of dollar amounts). See this IBM article for a more in depth explanation and examples. The solution is to use types that work with powers of ten internally. In C#, you can use ‘decimal’ and in Java or Ruby, ‘BigDecimal‘, to avoid these problems.