java - GC应用程序运行缓慢之后

时间:2016-11-18 07:12:27

标签: java garbage-collection game-engine vsync

我有一个在JVM上运行的应用程序(游戏)。

游戏的更新逻辑(运行60次/秒)完成,大约25%使用它的“时间片”(1/60秒),然后休眠剩下的75%。但是当GC收集器运行时,它会上升到75-200%,并在其余的执行中保持不变。

游戏使用大约70Mb的堆并且增长大约1-2mb / s。当GC运行时,它会回到70Mb,因此没有真正的内存泄漏。我将来会尝试降低这个数字,但在这个范围内它应该不是问题。

我正在使用没有运行时参数或标志的JVM 8,不确定哪个GC会给我。

我已经尝试将堆设置为不同的大小,但它不会影响这种现象。

我有两个理论可以解释为什么:

  1. GC无意中将我的堆分段,导致更新循环中的缓存废弃。我有逻辑,它可以从数据接近中获益,因为它会循环并更新它。可能是它将一些数据改组到旧区域,同时保留一些年轻人(托儿所)?

  2. 突然的GC处理触发了我的操作系统,让它意识到我的主要更新步骤不需要像现在这样多的CPU资源,降低了它的优先级。 (但是,即使我跳过thread.sleep()来暂停未使用的CPU使用情况,这种现象仍然存在。

  3. 你怎么看?我的理论是否合理,可以对它们做些什么,或者我是否需要切换到C语言?我对GC的了解有限。

    P.S。作为附注,通常更新()在GC后75%结束。当我得到200%的数字时使用VSync。

2 个答案:

答案 0 :(得分:0)

  

你怎么看?我的理论是否合情合理,

第一种理论似乎是合理的,但第二种理论则不然。

  

可以做任何关于他们的事情

你可以通过以下方式改进:

  1. 增加最大堆大小。
  2. 切换到低暂停收集器。
  3. 基于分析应用程序的结果的性能优化
  4. 试图降低垃圾产生率。
  5.   

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

    C和C ++会为您提供更可预测的行为,因为没有什么可以移动对象。如果您具备相应的技能并付出努力,那么能够在C和C ++中获得更好的性能,尤其是在进行图形/渲染时。但是,这些都是很大的“如果”。

答案 1 :(得分: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%,现在我将把自己的帖子标记为答案。

修改 那只是一个混乱的男人的谣言。上面只给了我一个小的性能提升 - 其余的是由于应用程序中的一个错误,因此不能证明架构的变化。压缩GC有点帮助。