创建并使用临时堆
我正在用java开发一款游戏,基本上每1/60秒更新一次。 在这样的更新过程中,大量的数据被创建,传递,然后不参考,让我们调用这个数据DTO的。 据我了解,JVM和OS将这些数据存储在程序堆中。 堆就这样建立起来,直到JAVA GC开始运行,这些分析将所有未被引用的数据标记为空闲并准备好被重用。
现在,我看到它的方式,这是不必要的,并且偶尔会出现滞后。 我想解决这个问题的方法是将一块分配的内存用作临时堆。 这个堆用于存储所有在更新间隔期间创建并传递的临时内容。 而且一旦我达到更新结束时,就不需要任何分析,但我可以简单地说整个块都是免费的,并且以这种方式在更新后重新使用相同的堆空间更新。 有点像尾递归堆栈帧。
另一个解决方案是只使用可变DTO对象并分配一堆并重用它们,但我喜欢利用这些优势使事物尽可能不可变。
这是一个努力来说明我的意思是代码:
void start(){
Data data = System.allocateDatainMb(500); //allocate 500Mb of virtual memory
MagicHeap() mh = System.createAMagicHeap(data); //make a heap of it
mh.use(); //set all constructors to allocate on this heap
while(true){
update();
mh.clear();
}
}
void update(){
TmpData dto = Gamesystem.createALargePieceOfTemporaryData();
someClass.doUpdateStuff(dto);
}
我不太了解Java如何管理内存,但我希望你明白我的意思。
在某种程度上可能吗?
我可能会错过一些东西,但我很肯定你不能用Java来做,因为它会干扰Java自己的内存管理。 毕竟,Java旨在将用户从低级内存管理例程中屏蔽掉。
因此,我建议去你提到的DTO池方法。 一种改进方法可能是隐藏增变器(例如setter和其他变异方法),并且只允许工厂方法等访问它们(例如通过使用包私人可见性)。 然后有工厂创建/重用看似不可变的实例并管理池。 你甚至可以处理暂时的“溢出”,也就是说,当你需要一些DTO的实例时,实际上会提供一些DTO。
然而,如果你仔细想想,如果使用得当,你可能会发现很多对象认为它们的寿命周期较短。 这可能只是一些计算的中间结果(如向量/矩阵数学),您在下一帧中不需要这些结果,但这些结果通常可以在创建后立即丢弃,并且在某些情况下也可以避免(例如,如果您手动使用基元或具有可变中间物体)。
你试图做的是智取JVM。 这不是你想要做的。 如果你真的需要直接使用内存分配,Java不是一种合适的语言。
Java的GC已经过优化,可以处理很多短暂的对象,它希望能够在添加之后不久从内存中释放大部分内容。 设置某种缓存系统的方式实际上可能会降低性能,因为现在无法从内存中释放这些对象,这意味着堆的空间会更少,并且(完整)GC暂停将更频繁。 这是缓存系统本身产生的任何开销的补充。
这并不意味着你应该忽略Java的内存问题。 您应该避免不必要地创建对象,更重要的是,您应该避免将对象引用放在超过需要的位置,以便您可以让GC对其进行清理。 调整GC以适应您的程序需求并确保您使用现代G1 GC可能也是有益的。
与任何性能调整一样,实际测量更改的性能差异非常重要。 对于你认为会更快的预感会导致你付出努力并增加复杂性,从而获得一点收获,或者性能下降。 确保你有真实的数字来备份任何性能问题。
链接地址: http://www.djcxy.com/p/81429.html