7

我有一个复杂的大型多线程应用程序,我正在向其引入新功能。

我添加了一个对专业硬件的调用(通过供应商提供的 JNI 库)。然而,在调用(非常快的)函数之前,需要预先完成一些工作来填充发送给它的数据结构。

然而,应用程序的 GC 配置文件非常不稳定/糟糕,并且这些填充步骤中的一些似乎被 GC 打断了。这很重要,因为在这些事件中的第一个和移交给硬件资源之间的时间需要保持恒定或尽可能恒定。

有没有办法说“为 GC 同步”,这些操作不会在停止世界 GC 暂停期间被阻止?

在 RHL5.5 上使用 64 位 1.7 JDK

谢谢

4

4 回答 4

3

如果实际上是在完整垃圾收集期间您遇到了问题,那么问题是您可以做些什么来降低这些完整垃圾收集扫描的频率。

首先,尝试分析什么情况下会触发这些全扫描,你的堆空间是否普遍不足?如果是这样,为什么您经常在堆上运行不足(某处是否存在潜在泄漏?)

此外,在次要(更快)垃圾收集期间,对象会从年轻代(伊甸园和幸存者 1)移动到幸存者 2。如果它不适合幸存者 2,它们将被移动到终身,如果没有空间够长,你触发全扫。所以,如果你的年轻代很大,并且你有一定数量的长时间运行的对象,这可能会导致问题。

归根结底,您必须对其进行分析。分析您的应用程序,并确定您看到完整垃圾收集的时间和原因,然后调整您的应用程序以降低它们的频率或潜在地确保它们非常罕见,您可以“控制”它们何时发生。

于 2013-03-26T12:21:24.567 回答
2

如果您正在构建一个新的时间敏感任务,并且无法使用该任务修复 JVM 的 GC 行为,那么另一种选择是您可以将任务移至单独的 JVM。

进程间/机器通信意味着有更高的最低性能,但在进行 JNI 通信的单独 JVM 实例中,您可以比在父进程中更自由地调整 GC,从而更好地控制波动。

于 2013-03-27T02:57:55.843 回答
2

为了完整起见,您还可以使用实现实时 Java (RTSJ) 的 JVM。

在实时 JVM 中,您可以在不会被 任何GC 活动中断的线程中执行对时间敏感的任务。不幸的是,现在可用的 RT JVM 并不多。

于 2013-03-26T21:18:22.593 回答
2

GC 行为不是确定性的,因此您无法确保同步。

我想到了三个选项:

  • 您是否创建了大量对象来填充每个调用的数据结构?也许您可以重复使用它们来避免填充堆和 GC 自动调用。
  • 运行具有更多预分配内存的 VM 以分隔 gc 调用。
  • 当对您的应用程序无害时,您自己调用 System.gc()。这个调用只是一个建议(JVM可以忽略它),但我会试一试。

无论如何,满足您需求的最佳选择是使用真正的实时语言实现而不是 Java

于 2013-03-26T11:56:33.250 回答