我有一个程序接收UDP数据包,从中解析一些数据,并将其保存到多个线程的数据库中。它使用Hibernate和Spring via Grails(GORM独立)。
它可以在一台服务器上正常工作,它可以快速启动(每个数据包20-30毫秒 - 除了JIT启动时的第一个 - )并在一段时间内稳定在50-60毫秒。
但是,在更新,功能更强大的服务器中,它会快速启动但逐渐变慢(每个数据包达到200毫秒甚至300毫秒,总是使用相同的负载)。然后,当JVM执行完整的GC(或者我从Visual VM手动执行)时,它会再次变快并且循环重新开始。
关于什么可能导致此行为的任何想法?随着Old Gen填满,它似乎变得越来越慢。伊甸园填补速度很快,但GCs暂停似乎很短暂。它在旧服务器上运行正常,所以让我感到困惑。
服务器规格是:
答案 0 :(得分:2)
您可以尝试使用JVM版本支持的G1吗?
如果应用程序具有以下一个或多个特征,则使用CMS或Parallel Old GC垃圾收集器运行的应用程序将有助于切换到G1。
(1)完整的GC持续时间太长或太频繁。 (2)对象分配率或促销率差异很大。 (3)不期望的长垃圾收集或压实暂停(超过0.5至1秒)
答案 1 :(得分:0)
我不可能说您的应用程序/服务器VM默认值是否有任何问题。
尝试添加-XX:+ PrintGCDetails以了解有关垃圾收集时年轻和老一代的更多信息。根据这些值,您的初始堆大小约为525MB,最大堆大约为8.4GB。 JVM将根据需求调整堆的大小,并且每次调整此堆的大小时,所有年轻代和旧代都会相应调整大小,这将导致完整GC。
此外,您的标志指示UseParallelGC,它将使用多个线程执行年轻代集合,但旧的gen仍然使用单线程连续收集。
NewRatio的默认值是2,这意味着Young gen占用堆的1/3,旧版占用堆的2/3。如果你有太多的短生命对象,请尝试调整年轻的基因大小,并且现在尝试使用7u65可能会尝试使用G1 GC。
但在调整之前我强烈建议你 (1)对GC日志进行适当的分析 - 在慢响应时间内查看是否有任何Full GC (2)尝试Java Mission Control。用它来监控远程服务器进程。它的功能丰富,你会知道更多关于GC的信息。
答案 2 :(得分:0)
您可以使用-XX:+ PrintGCDetails选项查看每个GC的发生频率。
但是,我不认为这是GC问题(或GC papameters)。正如您在帖子中所说的那样,程序运行正常,但当它被移动到新的快速机器时会出现问题。我的猜测是你的程序存在一些瓶颈,这反过来会减慢对已分配对象的释放引用。因此,内存会累积,VM会花费大量时间进行GC和内存分配。
在其他方法中,为包进程分配堆内存的过程,以及使用者将包内存保存到DB后回收此内存。但消费者无法赶上手续速度。
所以我的建议是检查你的程序并做一些测量