I’m working on a real-time game application. Most of it is written in Java, but recently I decided to experiment with moving some of the initialization procedures into JRuby scripts in order to maximize the ease for the player to modify how the world is generated.
As a start, I decided to move the map generation into a JRuby script. At present, this boils down to the following Java code:
ScriptingContainer container = new ScriptingContainer();
container.put("$data", dataPackage);
container.runScriptlet(PathType.RELATIVE, scriptName);
dataPackage = (BlockMapGenerationDataPackage)container.get("$data");
The data package contains all the information necessary for the Java program to produce the final terrain and render it, and it also contains the necessary data in order for the Ruby script to be able to craft all manner of maps. In particular, it contains a rather large array (currently 1000 x 1000 x 15). To test whether the Ruby script was working, I’ve stripped out the entire map generation algorithm and put in the following extremely simple test:
require 'java'
Dir["../../dist/\*.jar"].each { |jar| require jar }
for i in (0...$data.getWidth())
for j in (0...$data.getDepth())
$data.blocks[i][j][0] = Java::BlockMap::BlockType::GRASS
end
end
This is executed only once upon initialization. Now when this was all implemented in Java, with far more memory intensive generation algorithms, there were no performance or memory issues of any kind. The game ran smoothly at hundreds of frames per second at very high resolutions on an old laptop with a 1000 x 1000 x 15 map. However, when the Java generation code is replaced by the above JRuby script, the program appears to suffer some memory consumption issues: the frame rate drops by about 30-40 fps and the program freezes for maybe a 10th of a second at an impressively consistent periodic rate of about once every three seconds. Profiling and various tests reveal that the only possible culprit is the Ruby script.
Moreover, if the size of the map is drastically reduced, say to 100 x 100 x 15, then these issues more or less disappear.
I’ve tried various things like adding container.terminate(); or container.clear(); after the Java code to execute the script, but I really don’t understand the source of the issue or how to fix it. I’d greatly appreciate if someone could explain what’s going wrong here and whether or not this can be fixed!
It might be best to make the map creation routine a separate app altogether that chains to the java app.
I’m pretty sure that the memory layout of arrays in JRuby is going to be different and that could be causing your problems–The map object itself may be created with a different memory layout that is requiring some ongoing JRuby interaction whenever it is accessed, or it could be something as simple as creating Integers instead of ints and you aren’t noticing it because of autoboxing (Again, TOTAL guess since I can’t see data types)