2016-11-18 65 views
4

后,我有一个JVM上运行的应用程序(游戏)。爪哇 - GC应用程序运行速度慢

游戏的更新逻辑(运行60次/秒)与它的“时间片”(1/60秒)的使用约25%完成后,然后睡掉剩下的75%。但是,当GC采集器运行时,它会上升到75-200%,并在其余的执行阶段停留在那里。

游戏采用约堆的70MB和长约1-2MB /秒。 GC运行时会回到70Mb,所以没有真正的内存泄漏。我将在未来尝试降低这个数字,但在这个范围内它不应该是一个问题。

我使用JVM 8没有运行时参数或标志,不知道哪个GC,这将使我。

我试过设置堆大小不同,但不影响此现象。

我有两个理论,为什么这可能是:

  1. 的GC无意碎片堆我在导致缓存捣毁的更新循环的方式。我已经从逻辑中获得了很大的收益,因为它通过循环并更新它。难道它会将一些数据转移到旧区域,同时保留一些在年轻人(苗圃)?

  2. 突然GC处理触发我的操作系统,使其认识到,因为它目前,降低其优先级我的主要更新胎面并不需要这么多的CPU资源。 (但是,现象持续,即使我跳过了Thread.Sleep()睡觉关闭未使用的CPU占用率。

你觉得什么是我的理论似是而非,可以被任何关于他们做,还是我需要切换到C语言?我的GC的知识是有限的。

PS作为一个侧面说明,一般更新()在75%GC后结束。使用垂直同步时,当我喜欢200%的数字它。

+0

也许比较缓存未命中和相关的统计信息与'perf record'?还有,哪个JVM?哪个收藏家?哪些命令行标志? – the8472

+0

谢谢,我在帖子中添加了一些信息。不知道你的意思是“pref记录”虽然... – Jake

+0

https://perf.wiki.kernel.org/index.php/Tutorial#Sampling_with_perf_record,你应该启用GC日志记录来获取有关暂停时间的信息(请参阅如何做到这一点的JVM文档) – the8472

回答

0

不再有效:

我做了一个测试,完全毁了我的架构。我有这个,这是应用程序的瓶颈:

class Physics{ 
    Vec2 centre; 
    Rec hitbox; 
    Vec2 speed; 
    Vec2 acc; 
    ... 

    public void update(){ //critical method 
     centre.doThings(); 
     hitbox.doThings(); 
     etc... 
    } 

} 

并将其更改为仅使用原语:

class Physics{ 
    double centreX,centreY; 
    double x1,x2,y1,y2; 
    double speedX,speedY; 
    double accX,accY; 
    ... 

    public void update(){ //critical method 
     implementation of methods above... 
     etc... 
    } 

} 

这因为,至少,JAVA保证一类原始成员被存储在它们在堆的类标题下面声明它们的顺序。尽管对象的引用可能是堆的另一端的地址。

这和一个压缩GC一起给了我一个可爱的提升,我相信增加缓存命中。它摧毁了我的建筑,但这是我愿意付出的代价。

游戏现在运行稳定的15%,现在我打算将自己的帖子标记为答案。

编辑: 这只是一个混乱的人的ramblings。以上只是给了我一点小小的性能提升 - 其余的原因是由于应用程序中的错误,因此没有证明架构改变是正确的。压缩气相色谱虽然有所帮助。

0

你是怎么想的我的理论是否合理

第一种理论是合理的,但第二个不是。

  1. 增加最大堆大小:

    可任何有关他们

    你可能改善的事情要做。

  2. 切换到低暂停收集器。根据分析应用程序结果
  3. 性能优化
  4. 试图降低垃圾产生的速度。

还是我需要切换到C或C++?

C和C++会给你更多可预测的行为,因为没有任何东西会移动物体。如果你有适当的技能并付出努力,你应该能够在C和C++中获得更好的性能,尤其是在进行图形/渲染时。但是,那些大“如果”。

+0

谢谢Steven,1。我试着增加堆大小,但无济于事。当然,它延长了GC的首次到达,但其效果保持不变。 – Jake

+0

2.我很担心我不得不深入了解GC。 – Jake

+0

3.我不确定我的意思 – Jake