4

背景:

我们有一个供应商提供的 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

  • 回声“::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

  • 交换-s

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


4

2 回答 2

1

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

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

只有在更改后问题仍然存在时,我才会尝试调查替代轨道,例如内存碎片。

编辑:

从您的 memstat、prstat 和 vmstat 输出,很明显您的系统虚拟内存不足。完全没有必要调查内存碎片等其他异常原因。您的可用 RAM (~1.5G) 比可用虚拟内存 (~800MB) 多。这意味着有很多未使用(尚未)的内存预留。同样,只需添加一些交换空间即可解决此问题。这不会对性能产生任何影响,因为您有足够的 RAM。

编辑:(第 2 部分)

现在我们知道您正在使用 ZFS,因为您的应用程序最多可以使用 8 GB(如果我们考虑到非堆内存,甚至更多),您应该减少最大 ARC 大小以允许立即将这 8 GB 用于 JVM,而不是依赖操作系统正在执行的自我调整,这可能会因交换空间过小而感到困惑。有关如何执行此操作的详细信息,请参阅ZFS evil 调整指南中的限制 ARC 缓存一章。

于 2012-02-29T15:34:36.717 回答
0

如果您的 main+swap 空间已用完,您可能会收到此错误。虽然如今 2 GB 的交换空间非常小,但如果您必须使用交换空间,您确实会遇到性能问题,因为这意味着您正在强制应用程序交换到磁盘。

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

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


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

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

于 2012-02-29T14:57:10.667 回答