当前位置: 首页 > 知识库问答 >
问题:

Java应用程序变得越来越慢,直到执行完整的GC

逄俊力
2023-03-14

我有一个程序,它接收UDP包,从包中解析一些数据,并保存到一个数据库中。它通过Grails使用Hibernate和Spring(GORM独立)。

它在一台服务器上工作正常,启动速度很快(每个数据包20-30毫秒-除了JIT启动时的第一个数据包-),一段时间后稳定在50-60毫秒。

然而,在更新、更强大的服务器中,它启动速度很快,但逐渐变慢(每个数据包达到200ms甚至300ms,负载始终相同)。然后,当JVM执行完整的GC时(或者我从VisualVM手动执行),它会再次变快,并重新开始循环。

你知道是什么导致了这种行为吗?随着老一代人的补充,速度似乎越来越慢。伊甸园很快就填满了,但地面军事系统的暂停时间似乎很短。它在旧服务器上运行正常,所以我很困惑。

服务器规格如下:

  • 旧服务器:英特尔至强E3-1245 V2@3.40GHz,32 GB RAM,无ECC
  • 新服务器:英特尔至强E5-1620@3.60GHz,64 GB RAM,带ECC
  • 操作系统:Debian 7.6
  • JVM:
    • java版本“1.7.0_65”
    • Java(TM)SE运行时环境(构建1.7.0_65-b17)
    • Java热点(TM)64位服务器虚拟机(构建24.65-b04,混合模式)
      < li >旧服务器:在没有特殊RAM或GC参数的情况下运行,PrintFlagsFinal给出:-XX:InitialHeapSize = 525445120-XX:management server-XX:MaxHeapSize = 8407121920-XX:UseCompressedOops-XX:UseParallelGC < li >新服务器:尝试强制相同的标志,相同的结果。 < li >旧服务器似乎支持UseFastStosb,默认情况下它是启用的。在新服务器中强制它会导致一条消息,说它不受支持。

共有3个答案

毋城
2023-03-14

您可以使用-XX:printgccdetails选项来查看每个GC发生的频率。

不过我觉得不是GC问题(或者GC papameters)。正如你在帖子中所说,程序运行正常,但当它被转移到一个新的快速机器上时,问题就出现了。我猜你的程序中有一些瓶颈,这反过来会减缓释放对已分配对象的引用。因此,内存累积和VM使用大量时间进行GC和内存分配。

换句话说,为包进程分配堆内存的过程,在包内存保存到DB后,使用者回收该内存。但消费者无法赶上程序速度。

所以我的建议是检查你的程序并做一些测量

汤玉宸
2023-03-14

我不可能说您的应用程序/服务器虚拟机默认值是否有任何问题。

尝试添加 -XX: PrintGCDetails 以了解有关垃圾回收时年轻和旧一代大小的更多信息。根据这些值,初始堆大小从 525MB 左右开始,最大堆大小约为 8.4GB。JVM 将根据要求调整堆的大小,每次调整此堆的大小时,所有年轻和老一代都会相应地调整大小,这将导致完整的 GC。

您的标志还表明UseParallelGC将使用多个线程进行年轻一代的收集,但旧一代仍然使用单线程进行串行收集。

NewRatio 的默认值为 2,这意味着 Young gen 获取堆的 1/3,而 Old gen 则采用堆的 2/3。如果你有太多短生命物体,试着调整年轻一代的大小,现在你使用的是7u65,可能会给G1 GC一个尝试。

但是在进行调优之前,我强烈建议您(1)通过获取GC日志进行适当的分析-看看在您的缓慢响应时间内是否有任何完整的GC。(2)尝试Java任务控制。使用它来监视远程服务器进程。它的功能非常丰富,您将了解有关GC的更多信息。

姬博瀚
2023-03-14

您可以尝试使用JVM版本支持的G1吗?

如果应用程序具有以下一个或多个特征,则使用 CMS 或并行旧版 GC 垃圾回收器运行的应用程序将有利于切换到 G1。

(1) 完整GC持续时间太长或太频繁。(2) 对象分配率或提升率差异很大。(3) 不需要的长时间垃圾收集或压缩暂停(超过0.5到1秒)

 类似资料:
  • 为什么javascript函数中的jQuery函数每次被点击时就会越来越多地触发?点击次数足够多,每次点击执行100+次。 JsFiddle我只是很好奇为什么它是这样工作的。

  • 我是android开发的新手,我的应用程序在调用特定活动时会崩溃。(“governanaceactivity”是活动的名称)当我从MainActivity调用治理活动时,我的应用程序会崩溃,其他菜单工作得很好,唯一的问题是这个活动。 这是GovernanceActivity **所有其他活动都很好,只有这个活动有问题 这是我的宣言** Blockquote 05-21 03:09:53.747 1

  • 我有一个简单的选择查询,返回200行。查询被迭代 1437 次。技术 : java 8, Spring靴 2.1.3.发布, 雄猫, Hibernate 在每次迭代时,查询都会变慢。第一个查询需要55毫秒,最后一个查询需要702毫秒 但是,当我在Junit“@RunWith(SpringJUnit4ClassRunner.class)”中启动相同的查询时,查询不会变慢。每次查询需要 - 37 毫秒

  • 我正在使用Firebase来保存我的数据。我试图在活动中分离Firebase方法和我的方法。例如,我已经创建了一个名为"Firebase method odsHelper"的类,在那里我想编写所有的Firebase方法。例如,"getAllUser"方法应返回列表中的所有用户。我唯一的问题是它不起作用。 我不知道我做错了什么,所以如果你们能帮我。 碎片 FirebaseMethodHelper类

  • 我有一个Spring启动,Hibernate使用java应用程序。我部署它在一个jetty webserver与多个实例.如果我有太多(大于10)很多实例我得到 许多连接(10x实例)显示为空闲 ps: 实例的Hikari跟踪日志: 设置 没有记录任何有趣的事情。我认为这看起来很有趣-连接不可用 有什么办法可以调试这个吗?我也在java 7上,所以hikari 2.4.7

  • 前面提到多进程的并行可以提高并发度,那么进程是越多越好?一般遇到这种问题都回答不是,事实上,很多大型项目都不会同时开太多进程。 下面以支持100K并发量的Nginx服务器为例。 举个例子: Nginx Nginx是一个高性能、高并发的Web服务器,也就是说它可以同时处理超过10万个HTTP请求,而它建议的启动的进程数不要超过CPU个数,为什么呢? 我们首先要知道Nginx是Master-worke