需要Solaris和Java连续内存澄清

时间:2012-02-29 14:04:00

标签: java solaris virtual-memory sunos

背景

我们有一个供应商提供的Java应用程序,它有一个稍大的Java堆。没有太多信息,应用程序对我们来说是一个黑盒子,但我们觉得我们需要自己尝试调整性能并解决问题。

64位SunOS 10机器有16GB内存,唯一运行的非系统应用程序是这个应用程序的JVM。 64位JVM在JBoss中运行,我认为与此讨论无关,最大堆大小为8GB,我认为这是相关的。

最近的问题是我们遇到了各种内存不足错误。发生这些错误时,堆未满,并且错误询问“Out of Swap Space?”。供应商希望我们将交换从2GB增加到4GB,这是在一个16GB的系统上,而且应用程序只有8GB。我们认为这对于表现来说是一个坏主意。

我的问题:

因此我们发现有一件事是文件缓存耗尽了所有剩余的可用内存以提高性能。通常不是问题,但它显然会破坏记忆。由于Hotspot JVM需要连续的内存空间,我们已经了解到这种内存碎片会导致使用未分段的交换空间。

但是,我不确定我是否理解碎片与连续记忆要求之间的关系。当然,碎片只是指物理公羊的碎片化。使用虚拟内存,完全可以分配一个连续的ram块,而不会被连续的ram块支持。换句话说,一个非连续的物理内存块在正在运行的进程中看起来像一块连续的虚拟内存。

所以,我猜,那里没有一个句子问题,但是有没有人对这个问题有更多了解并且可以加入?在64位系统上引用此连续内存问题的任何链接?

到目前为止我发现了什么:

到目前为止,我发现的“连续内存”问题的每个引用都与32位地址系统中虚拟地址空间的布局有关。当我们运行64位系统时(我认为,48位寻址),有足够的虚拟地址空间来分配大的连续块。

我一直在互联网上查找这些信息,但迄今为止无法找到我要查找的信息。

更新:

  • 要明确的是,我并没有试图找到我为什么会收到OOM错误的答案,而是试图理解可能碎片化的系统RAM与java所需的连续虚拟内存块之间的关系。
  • prstat -Z

ZONEID    NPROC  SWAP   RSS MEMORY      TIME  CPU ZONE  
     0       75 4270M 3855M    24%  92:24:03 0.3% global

  • echo“:: memstat”| mdb -k

Page Summary                Pages                MB  %Tot    
------------     ----------------  ----------------  ----  
Kernel                     326177              2548   16%  
ZFS File Data              980558              7660   48%  
Anon                       561287              4385   27%  
Exec and libs               12196                95    1%  
Page cache                  17849               139    1%  
Free (cachelist)             4023                31    0%  
Free (freelist)            156064              1219    8%  

Total                     2058154             16079  
Physical                  2042090             15953  

  • 我之前认为ZFS文件数据是免费提供的内存,我从那时起就知道情况并非如此,很可能是造成错误的原因。

  • vmstat 5 5


kthr      memory            page            disk          faults      cpu  
r b w   swap  free  re  mf pi po fr de sr vc vc vc --   in   sy   cs us sy id  
0 0 0 2161320 2831768 12 55 0  0  0  0  0  3  4 -0  0 1089 1320 1048  1  1 98  
0 0 0 819720 1505856 0  14  0  0  0  0  0  4  0  0  0 1189  748 1307  1  0 99  
0 0 0 819456 1505648 0   1  0  0  0  0  0  0  0  0  0 1024  729 1108  0  0 99  
0 0 0 819456 1505648 0   1  0  0  0  0  0  0  0  0  0  879  648  899  0  0 99  
0 0 0 819416 1505608 0   1  0  0  0  0  0  0  3  0  0 1000  688 1055  0  0 99  

  • 当应用程序以健康状态运行时,会执行这些命令输出。我们现在监视所有上述内容并记录它以防我们再次看到交换空间错误。

  • 以下是在JVM增长到8GB然后重新启动之后。这样做的结果是ZFS ARC缩小(达到26%RAM),直到它再次增长。现在看起来怎么样?

  • vmstat 5 5


kthr      memory            page            disk          faults      cpu
r b w   swap  free  re  mf pi po fr de sr vc vc -- --   in   sy   cs us sy id
0 0 0 1372568 2749528 11 41 0  0  0  0  0  2  3  0  0  713  418  539  0  0 99
0 0 0 3836576 4648888 140 228 0 0 0  0  0  0  0  0  0 1178 5344 1117  3  2 95
0 0 0 3840448 4653744 16 45 0  0  0  0  0  0  0  0  0 1070 1013  952  1  3 96
0 0 0 3839168 4652720 6 53  0  0  0  0  0  0  0  0  0  564  575  313  0  6 93
0 0 0 3840208 4653752 7 68  0  0  0  0  0  3  0  0  0 1284 1014 1264  1  1 98

  • swap -s

总共:分配4341344k字节+ 675384k保留= 5016728k使用,3840880k可用


2 个答案:

答案 0 :(得分:1)

当错误消息显示交换空间可能不够大时,我通常会信任它并显着增加交换大小。

我建议你先做,最高4 GB甚至8 GB,看看会发生什么。扩大掉期对业绩没有任何影响。这是一个普遍的误解。影响性能的是缺少RAM,而不是太大的交换区域。

只有在更改后问题仍然存在时,我才会尝试研究其他跟踪,例如内存碎片问题。

修改

从您的memstat,prstat和vmstat输出,很明显您的系统没有虚拟内存。绝对没有必要调查其他异常原因,如内存碎片。你有比免费虚拟内存(~800MB)更多的空闲RAM(~1.5G)。这意味着有很多未使用的(尚未)内存预留。再次,只需添加一些交换空间来修复它。由于您有足够的RAM,因此会对性能产生任何影响。

编辑:(第2部分)

现在我们知道您正在使用ZFS,因为您的应用程序可以使用高达8 GB(如果我们考虑非堆内存,甚至更多),您应该减少最大ARC大小以允许这些8 GB的立即可用性JVM,而不是依赖于操作系统正在进行的自我调整,目前可能会由于尺寸不足的交换而混淆。有关如何执行此操作的详细信息,请参阅Limiting the ARC cache chapter in the ZFS evil tuning guide

答案 1 :(得分:0)

如果您的主+交换空间已用完,则可能会出现此错误。虽然目前2 GB的交换非常小,但如果您不得不使用交换空间,则会出现性能问题,因为这意味着您要强制应用程序交换到磁盘。

在这种情况下增加最大堆将无济于事,因为问题是缺少内存。它甚至可能使它更有可能发生。

解决方案可能是使用更少的内存(通过减少系统上运行的其他应用程序)或增加主内存(如今服务器的16 GB并不多,我的家用电脑有24个;)


编辑:我看到的另一件事导致这个问题是大量使用带内存的直接内存。例如默认情况下,最大直接内存与最大堆大小相同。这意味着在使用所有堆之前,您的应用程序可能使用大约8 GB的直接内存。应用程序可以发现操作系统没有足够的主+交换空间来为堆分配内存并且可能会死掉。

我倾向于尽可能多地使用直接内存,但这样做是为了避免使用大量堆。 ;)