Swapping Between JRuby Embed Methods
May 8, 2012, 10:23 AM
When going about making Ruby in XPages work, I had to figure out which of the three JRuby embed methods to use: Core, JSR 223, and BSF. For my purposes, it seems like the need for BSF was obviated by JSR 223 (there are some differences, but I'm not sure they matter to me), so it's really a choice between the first two. I've tried both, and I keep swapping between them (the next beta, if things stay stable, will likely switch back to Core) and between various configurations inside them, due to various problems I've run into on a couple points:
javax.*classes and any custom classes in the NSF. If I just go the default route for each embedding method, Ruby can't access those classes, but setting the classloader may or may not work with a given configuration.
- Clean Termination. This one's tough to tell. The "Core" route has a
.terminate()method, but I'm not sure if this is strictly necessary or if it's just a good idea to do it when you're going to be spinning up a lot of runtimes, but otherwise it's fine to let the garbage collector do its thing. This should give me an excuse to try out some of that heap dump stuff.
- Independence. By this I mean that, ideally, each page load and its associated script libraries will be completely independent of future calls - for example, a class declared in a script library should only be available when that library is loaded for the page and not otherwise. This conflicts with performance heavily - the fastest way to do it is to just have a single runtime, either for the JVM (via a singleton) or for the application, but this could lead to lingering methods and classes.
On all these metrics, it seems like Core is more flexible, but JSR 223 is the "right" way to do embedded scripting, being as it is the overarching framework for scripting languages in Java now.
Regardless of which of the two I choose, I have four different types of runtimes to choose from: threadsafe, concurrent, single-thread, and singleton. Those are more or less in order of "most independent" towards "fastest". However, it's not as simple as just choosing how fast or safe I want the code to be - I've also run into weird problems with some setups regarding the classloader and
OutOfMemoryErrors. When I use the singleton and single-thread routes, everything is speedy, but class loading works unpredictably - it seems to SOMETIMES use the JSF runtime classloader, sometimes not, and sometimes it's different between my dev and production servers. I'm not entirely sure what causes the memory problems, but I think I've seen them on the concurrent and threadsafe routes.
For now, I have it set to use Core with the single-thread context and calling
.terminate() at the end of each request. It SEEMS to be stable, but the home page in particular takes painfully long to load. I'll have to fiddle with it some more before I can safely release another beta.