JRuby,大型数组和实时应用程序中的性能问题

时间:2011-05-10 22:13:03

标签: java performance jruby real-time

我正在开发一个实时游戏应用程序。其中大部分都是用Java编写的,但最近我决定尝试将一些初始化过程转移到JRuby脚本中,以便最大限度地方便玩家修改世界的生成方式。

首先,我决定将地图生成移动到JRuby脚本中。目前,这归结为以下Java代码:

ScriptingContainer container = new ScriptingContainer();
container.put("$data", dataPackage);
container.runScriptlet(PathType.RELATIVE, scriptName);
dataPackage = (BlockMapGenerationDataPackage)container.get("$data");

数据包包含Java程序生成最终地形并呈现它所需的所有信息,它还包含必要的数据,以便Ruby脚本能够制作各种地图。特别是,它包含一个相当大的数组(目前为1000 x 1000 x 15)。为了测试Ruby脚本是否正常工作,我已经删除了整个地图生成算法并进行了以下非常简单的测试:

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

初始化时只执行一次。现在,当这些都是用Java实现的,具有更多的内存密集型生成算法时,没有任何类型的性能或内存问题。在具有1000 x 1000 x 15地图的旧笔记本电脑上,游戏以非常高的分辨率以每秒数百帧的速度平稳运行。但是,当Java生成代码被上面的JRuby脚本替换时,该程序似乎会遇到一些内存消耗问题:帧速率下降约30-40 fps,程序冻结的时间可能是十分之一秒,令人印象深刻的一致周期率约为每三秒一次。分析和各种测试表明唯一可能的罪魁祸首是Ruby脚本。

此外,如果地图的大小大幅减少,比如100 x 100 x 15,那么这些问题或多或少都会消失。

我尝试过各种各样的事情,例如在Java代码之后添加container.terminate();container.clear();来执行脚本,但我真的不明白问题的根源或如何解决它。如果有人能解释这里出了什么问题以及是否可以解决这个问题,我将不胜感激!

2 个答案:

答案 0 :(得分:2)

最好将地图创建例程作为一个单独的应用程序,链接到Java应用程序。

我很确定JRuby中数组的内存布局会有所不同,这可能会导致你的问题 - 地图对象本身可能会创建一个不同的内存布局,每当需要一些正在进行的JRuby交互时它是被访问的,或者它可能是像创建整数而不是整数这样简单的东西而你没有注意到它因为自动装箱(再次,因为我无法看到数据类型,所以总体猜测)

答案 1 :(得分:2)

你应该至少试验下标的顺序:[i] [j] [0]与[0] [i] [j]和[0] [j] [i]相比。