应用程序的内存是大还是小?

应用程序的内存是大还是小?

应该在内存容量大的少量实例(即机器)上运行应用程序,还是在内存容量小的大量实例上运行应用程序?哪种策略是最佳的?这个问题可能会经常遇到。在开发应用程序长达 20 年,且构建了 JVM 性能工程/故障排除工具( GCeasyFastThread,HeapHero)之后,我仍然不知道这个问题的正确答案。同时,我相信这个问题也没有非黑即白的答案。在本文中,我想与大家分享一下我对这个问题的看法和经验。

两个数十亿美元企业的故事

由于我们的 JVM 性能工程/故障排除工具已广泛应用于各大企业,因此我有机会看到世界级企业应用的实际实施情况。最近,我有机会参观了两家高速成长的科技公司(如果我说出他们的名字,读这篇文章的人都会知道)。这两家公司的总部都在硅谷。它们的业务是技术,因此在工程设计方面很有一套。它们是华尔街的宠儿,享有极高的估值。它们的市值高达数十亿美元。它们是现代企业蓬勃发展的典型代表。在我们的对话中,让我们称这两家企业为公司 A 和公司 B。

在内存大小方面,两家企业都采用了两个极端,这让我感到非常惊讶。公司 A 将堆大小(即 -Xmx)设置为 250GB,而公司 B 则将堆大小设置为 2GB:公司 A 的堆大小是公司 B 的 125 倍。两家公司都对自己的内存大小设置很自信。俗话说:"事实胜于雄辩",两家企业都在扩大规模,处理数十亿的关键业务交易。

两家公司都从事相同的业务,收入/市值大致相同,位于同一地理区域,在同一时间点采用两种极端的内存大小,这真是一次绝佳的体验。鉴于这种现实生活中的真实经验,正确的答案是什么?大内存还是小内存?我的结论是:如果你有一支优秀的团队,采用这两种策略都能取得成功。

大内存容量可能很昂贵

与内存容量小、实例数量多的情况相比,内存容量大、实例(即机器)数量少的情况往往成本较高。以下是基于美国东部(弗吉尼亚州北部)地区 AWS EC2 实例成本的简单计算:

m4.16xlarge - 256GB 内存 - Linux 按实例收费:3.2 美元/小时

T3a small - 2GB 内存 - Linux 按实例收费:0.0188 美元/小时

因此,要获得 256GB 内存容量,我们必须获得 128 个 “T3a small” 实例(即 128 个实例 x 2GB = 256GB)。

128 x T3a small - 2GB 内存 - Linux 按实例收费:2.4064 美元/小时(即 128 x 0.0188 美元/小时)

这意味着内存容量大、实例少的成本比内存容量小、实例多的成本高出 0.793 美元/小时(即 3.2 美元 - 2.4064 美元)。换句话说,"大内存、少实例 "策略的成本要高出 33%

当然,也可以提出另一种反驳意见:如果机器数量较少,可能需要更少的工程师、更少的电力、更少的不动产。服务器的修补和升级也会更容易。

业务需求

在某些情况下,业务本身的性质决定了应用程序的内存大小。下面是我们遇到的一个真实事件:当我们构建 HeapHero(堆转储分析工具)时,我们工具的内存大小必须大于其解析的堆转储文件。假设堆转储文件大小为 100GB,那么 HeapHero 工具的内存大小必须大于 100GB。别无选择。

假设你要缓存大量数据(比如 200GB),以最大限度地提高应用程序的性能,那么你的堆大小必须大于 200GB。你别无选择。因此,在某些情况下,业务需求将决定内存大小。

性能与故障排除

如果内存大小较大,那么垃圾回收停顿时间通常也会较长。垃圾回收是在应用程序中运行的一个进程,用于清理内存中未引用的对象。如果内存大小很大,那么内存中的垃圾量也会很大。因此,清理垃圾所需的时间也会很长。垃圾回收运行时,应用程序会停顿。不过,这个问题也有解决办法:

  • 您可以使用无暂停 JVM(如: Azul) [1]

  • 需要进行适当的 GC 调优以减少暂停时间。

同样,如果需要排除任何内存问题,就必须捕获应用程序的堆转储。堆转储基本上是一个文件,其中包含有关应用程序内存的所有信息,如存在哪些对象、它们的引用是什么、每个对象占用多少内存等等。大内存容量应用程序的堆转储也往往非常大。分析大容量堆转储也很困难。即使是世界上最好的堆转储工具,如 Eclipse Memory Analyzer(MAT)HeapHero,在解析超过 100GB 的堆转储时也会遇到非常大的挑战和困难。在测试实验室重现这些问题、存储这些堆转储文件、共享这些堆转储文件都是极大的挑战。

情感第一,理由第二

当阅读了乔纳·莱勒(Jonah Lehrer)撰写的 《为什么大猩猩比专家高明》 等书籍后,我相当确信,你先前的经验和情感在决定应用程序内存大小方面起着关键作用。我曾在一家大型金融机构工作。这家金融机构的首席架构师建议我们使用超大内存运行 JVM,他给出的理由是:“我们以前运行大型主机时,内存也非常大”😊。

总结

如果你在大型企业工作,那么 99.99% 的可能性是你可能无权决定应用程序的内存大小。因为坐在象牙塔里的精英/半仙们已经做出了决定😊。可能很难扭转或改变这一决定。 但如果你有选择或选项来做出决定,那么你对内存大小的决定很可能会受到你之前的经验和情绪的影响 😊。但无论如何,只要你有合适的团队,就不会出错(即选择内存容量大的少量实例或内存容量小的大量实例)。


1. D瓜哥注: 现在也可以使用 OpenJDK 11+,尤其是 OpenJDK 17+