From: Charles Oliver Nutter Date: 2007-12-22T23:42:03+09:00 Subject: Re: Experimental PATCH to improve thread performance Brent Roman wrote: > > Charles Oliver Nutter-2 wrote: >> >> I'd love to know what broke in JRuby. I tried both benchmarks and >> they're very snappy on my machine. We're making a big push to get JRuby >> threading solid, so please let us know what you've seen. >> >> > > I'd like to work with you on this after the holidays. > In the meantime, I've attached a java backtrace > of the failure in our dreaded "killer app" > Let me know if you can glean anything from it that will > help me create a simple test case for you. > > http://www.nabble.com/file/p14467248/jruby-1.1b1.backtrace > jruby-1.1b1.backtrace > > By the way, > The benchmark numbers I see here are very consistent with your claim > that JRuby is faster than Ruby 1.8.6. In this case, it's a lot faster: > > Unpatched 1.8.6 Patched 1.8.6 JRuby 1.1b1 Ruby 1.9 > Bench #1 22sec / 16 MB 4sec / 7 MB 3.5sec / 21 MB 0.06sec > Bench #2 35sec / 10 MB 15sec / 7 MB 2.8sec / 17 MB 0.36sec > > I realize that these numbers penalize JRuby for its JVM start up delay, > but, even so, it's clear that when Ruby 1.9 is finally ready, > it will be the horse to beat ;-) Oh, one other feature of JRuby might be interesting here, and interesting for Ruby 1.9, so I'm not totally OT). JRuby uses native threads, as you know. This increases the cost of spinning up many threads, since green threads are much cheaper. So in JRuby, I implemented an optional thread-pooling mode that uses Java's concurrency APIs. In this mode, threads are reused; the number of native threads used is only as high as the total number of threads running concurrently, and those threads get reused until they age out of the pool: CODE: t = Time.now; 100000.times { Thread.new {} }; p Time.now - t JRuby unpooled: 26.045 JRuby pooled: (-J-Djruby.thread.pooling=true) 3.572 Ruby 1.8.6: 0.537061 Ruby 1.9: 13.925661 (Note this doesn't test the time required for all threads to complete...just to construct them) JRuby's not quite as fast as MRI here, but that's mostly because we construct many more runtime structures per thread (like preallocating a frame stack 50 deep to safe the cost of allocating later) and I think we can probably approach MRI thread-spawning performance with a little work. For now, it's good enough. I would expect this same technique would apply well to Ruby 1.9, and probably give similar performance gains. I'd be happy to describe it if anyone's interested. - Charlie