Java垃圾收集和原子事件/停止gc暂停中断一系列函数调用

时间:2022-12-25 17:19:12

I have a complex large multithreaded application to which I am introducing new functionality.

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

I have added a call to a piece of specialist hardware (via a vendor supplied JNI lib). However before that (very fast) function is called some work is done beforehand to populate the data structure sent to it.

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

However the GC profile of the application is very choppy/bad and it seems that some of these population steps are being interrupted by GC. This matters because time needs to be kept constant or as constant as possible between the first of these events and the hand off to the hardware resource.

然而,应用程序的GC配置文件非常不稳定/不良,似乎这些填充步骤中的一些正被GC中断。这很重要,因为时间需要在第一个事件和切换到硬件资源之间保持不变或尽可能保持不变。

Is there a way to say, "sychronise for GC", these operations so that they won't be held up during stop the world GC pauses?

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

Using a 64bit 1.7 JDK on RHL5.5

在RHL5.5上使用64位1.7 JDK

Thanks

4 个解决方案

#1


3  

If it is in-fact during the full garbage collection you are experiencing the issues, then the question is what can you do to bring down the frequency of these full garbage collection sweeps.

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

First, try and analyse what circumstances triggers these full sweeps, are you running low on heap space in general? And if so, why are you frequently running low on heap (are there a potential leak somewhere?)

首先,尝试分析触发这些全面扫描的情况,一般来说,堆空间是否正常运行?如果是这样,为什么你经常在堆上运行不足(某处有潜在的泄漏?)

Also, during minor (the faster) garbage collections, objects are moved from the young generations (eden and survivor 1) to survivor 2. If it doesn't fit in survivor 2, they will be moved to tenured, if there isn't enough space in tenured, you trigger a full sweep. So, if your young generations are large, and you have a certain amount of long running objects, this might cause issues.

此外,在较小(较快)的垃圾收集期间,物体从年轻一代(伊甸园和幸存者1)移动到幸存者2.如果它不适合幸存者2,他们将被转移到终身,如果没有在终身房中有足够的空间,你可以触发一次完整的扫描因此,如果您的年轻一代很大,并且您有一定数量的长时间运行物体,这可能会导致问题。

In the end of the day, you have to analyse it. Profile you application, and determine when and why you are seeing full garbage collections, and then tune your application to make them less frequent or potentially ensure that the are so infrequent you can "control" when they happen.

在一天结束时,你必须分析它。描述您的应用程序,并确定您何时以及为何看到完整的垃圾收集,然后调整您的应用程序以减少它们的频率,或者可能确保您很少“控制”它们何时发生。

#2


2  

GC behaviour is not deterministic, so you cannot ensure synchronization.

GC行为不确定,因此无法确保同步。

Three options come to my mind:

我想到了三个选择:

  • Are you creating a lot of objects to populate the data structure for each call? Maybe you can re-use them to avoid filling the heap and GC automatic calls.
  • 您是否正在创建大量对象来为每个调用填充数据结构?也许你可以重复使用它们来避免填充堆和GC自动调用。

  • Run the VM with more pre-assigned memory to space the gc calls.
  • 使用更多预先分配的内存运行VM以隔离gc调用。

  • Call System.gc() yourself when is not harmful for your application. This call is just a suggestion (JVM can ignore it), but I'll give it a try.
  • 当您的应用程序无害时,请自行致电System.gc()。这个调用只是一个建议(JVM可以忽略它),但我会试一试。

Anyway the best option for your needs is to use a true Real-Time language implementation instead Java

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

#3


2  

Just for completeness, you could also use a JVM that implements Real-time Java (RTSJ).

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

In a real-time JVM, you can execute your time-sensitive task in a thread that will not be interrupted by any GC activities. Unfortunately, there is not many RT JVMs available out there these days.

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

#4


2  

If you're building a new time sensitive task, and cannot fix the GC behavior of the JVM using the task, then one other option is that you could move the task to a separate JVM.

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

Interprocess/machine communication will mean there is a higher minimum performance, but in the separate JVM instance that does your JNI communication you could tune GC with more freedom than you have within the parent process and thereby get more control over the choppiness.

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

#1


3  

If it is in-fact during the full garbage collection you are experiencing the issues, then the question is what can you do to bring down the frequency of these full garbage collection sweeps.

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

First, try and analyse what circumstances triggers these full sweeps, are you running low on heap space in general? And if so, why are you frequently running low on heap (are there a potential leak somewhere?)

首先,尝试分析触发这些全面扫描的情况,一般来说,堆空间是否正常运行?如果是这样,为什么你经常在堆上运行不足(某处有潜在的泄漏?)

Also, during minor (the faster) garbage collections, objects are moved from the young generations (eden and survivor 1) to survivor 2. If it doesn't fit in survivor 2, they will be moved to tenured, if there isn't enough space in tenured, you trigger a full sweep. So, if your young generations are large, and you have a certain amount of long running objects, this might cause issues.

此外,在较小(较快)的垃圾收集期间,物体从年轻一代(伊甸园和幸存者1)移动到幸存者2.如果它不适合幸存者2,他们将被转移到终身,如果没有在终身房中有足够的空间,你可以触发一次完整的扫描因此,如果您的年轻一代很大,并且您有一定数量的长时间运行物体,这可能会导致问题。

In the end of the day, you have to analyse it. Profile you application, and determine when and why you are seeing full garbage collections, and then tune your application to make them less frequent or potentially ensure that the are so infrequent you can "control" when they happen.

在一天结束时,你必须分析它。描述您的应用程序,并确定您何时以及为何看到完整的垃圾收集,然后调整您的应用程序以减少它们的频率,或者可能确保您很少“控制”它们何时发生。

#2


2  

GC behaviour is not deterministic, so you cannot ensure synchronization.

GC行为不确定,因此无法确保同步。

Three options come to my mind:

我想到了三个选择:

  • Are you creating a lot of objects to populate the data structure for each call? Maybe you can re-use them to avoid filling the heap and GC automatic calls.
  • 您是否正在创建大量对象来为每个调用填充数据结构?也许你可以重复使用它们来避免填充堆和GC自动调用。

  • Run the VM with more pre-assigned memory to space the gc calls.
  • 使用更多预先分配的内存运行VM以隔离gc调用。

  • Call System.gc() yourself when is not harmful for your application. This call is just a suggestion (JVM can ignore it), but I'll give it a try.
  • 当您的应用程序无害时,请自行致电System.gc()。这个调用只是一个建议(JVM可以忽略它),但我会试一试。

Anyway the best option for your needs is to use a true Real-Time language implementation instead Java

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

#3


2  

Just for completeness, you could also use a JVM that implements Real-time Java (RTSJ).

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

In a real-time JVM, you can execute your time-sensitive task in a thread that will not be interrupted by any GC activities. Unfortunately, there is not many RT JVMs available out there these days.

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

#4


2  

If you're building a new time sensitive task, and cannot fix the GC behavior of the JVM using the task, then one other option is that you could move the task to a separate JVM.

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

Interprocess/machine communication will mean there is a higher minimum performance, but in the separate JVM instance that does your JNI communication you could tune GC with more freedom than you have within the parent process and thereby get more control over the choppiness.

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