我有一个在独立JVM中运行的Java应用程序。该应用程序侦听一个或多个套接字上的数据,对数据进行排队,并调度线程将数据从队列中拉出并保留它。数据很宽,每条记录超过700个数据元素,尽管所有数据元素都是小字符串,整数或长整数。
应用程序运行一段时间,有时是30分钟到一小时,但随后我们会遇到一个或多个长时间的垃圾收集暂停。大部分暂停时间都花在对象复制时间上。系统时间相对于其他集合也很高。
以下是JVM详细信息:
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) 64-Bit Server VM (build 22.1-b02, mixed mode)
以下是JVM选项:
-XX:MaxPermSize=256m -XX:PermSize=256m -Xms3G -Xmx3G -XX:+UseG1GC -XX:-UseGCOverheadLimit
该进程是4个核心的任务集(全部在同一个套接字上),但几乎没有使用其中的两个。此框中的所有进程都固定到它们自己的核心(0 ansd 1未使用)。机器有足够的可用内存(20 + G),顶部显示使用2.5G RES存储器的过程。
以下是一些gc日志输出...
[Object Copy (ms): 2090.4 2224.0 2484.0 2160.1 1603.9 2071.2 887.8 1608.1 1992.0 2030.5 1692.5 1583.9 2140.3 1703.0 2174.0 1949.5 1941.1 2190.1 2153.3 1604.1 1930.8 1892.6 1651.9
[Eden: 1017M(1017M)->0B(1016M) Survivors: 7168K->8192K Heap: 1062M(3072M)->47M(3072M)]
[Times: user=2.24 sys=7.22, real=2.49 secs]
有关对象复制时间和系统时间如此之高以及如何纠正的任何想法?日志中有大量垃圾收集,几乎相同的Eden / Survivors /堆大小只需要10或20毫秒。
答案 0 :(得分:1)
3gb不是一个大堆,幸存者的大小也很小。在这些核心上运行的其他东西?你产生了多少垃圾,收集的频率是多少?您也可以尝试不使用G1GC。
答案 1 :(得分:0)
你需要 3千兆字节的堆吗?随着堆变大,垃圾收集暂停时间变长,因为(尽管不那么频繁),最终需要GC时还有更多工作要做。
通过设置最小值,您似乎以3 gig锁定堆。如果应用程序不需要3个演出,这将迫使它使用那么多..并且当3G最终需要被收集时导致一个巨大的停顿。
我花了很多时间调整Eclipse IDE的响应速度,并且很早就发现紧凑的堆大小具有比大的更好的“低暂停”特性。
除了JVM堆设置之外,您还可以确保代码“空出”数据元素&收集物品,因为它们被丢弃。
这是java.util
集合包中的标准做法,但您可能拥有可以从中受益的代码。 700多个记录特别适合这种做法,这有助于简化GC的工作,并通过“次要GC”扫描实现更好的清理。