如何估算内存的消耗
Performance Zone是由New Relic和AppDynamics支持的。New Relic和AppDynamics作为APM领域的领导者。有着备受瞩目的用户并为用户消减大量成本。
这个故事至少能够追溯到十年前,当我第一次接触到PHB,遇到了这样一个问题——“为了产品部署我们应该购买多大的server”。
这个崭新的系统上线已经九个月了。显然公司已经承诺提供整套的解决方式,包含硬件。
哦,乖乖,我是陷入麻烦之中了吗?我有几年的经验,我倒是能够试一试。
尽管我我全然没有信心。但我还是要解决问题。
经过在谷歌上四个小时的搜索,我依旧坐在那里。摆在我面前的还是那个令我感到困惑的问题:“怎样估算计算容量呢?”。
在这篇文章中我通过给你几个大致的纲领来开展这个主题,这些纲领是关于怎样预计你的那个全新的Java应用所需的内存。对于性急的人来讲。答案大概约等于5x(内存通过实时数据消耗量),并从那里開始微调。而对于那些对背后逻辑更感兴趣的人,请随我一起,我会引导你完毕推理。
首先。在没有具体信息之前。我不能用简单的几句话来回答这个问题。你的答案必须是根据性能要求而来的,所以刚開始的时候首先要澄清这点。
我并非说要用非常含糊不清的方式,譬如“这个系统须要在线支持700个用户”,但还有非常多更具体的关于延迟和吞吐量的细节。还要考虑到大量数据,以及使用模式。
预算也不应当被遗忘。我们都幻想着亚毫秒级的延迟,可是没有HTF银行那样的雄厚资金支持的话,非常不幸。它终将仅仅是一个梦想。
如今,我们如果你有了一些需求,下一步是创建负载測试脚本来模拟用户的行为。如果你能够同一时候在线启动这些的脚本。你就已经为获取答案建立基础了。正如你猜想的那样,下一步是測试。而不是瞎猜,可是会有一个警告。
实时数据的大小
也就是说,最佳内存配置须要捕获实时数据大小。
捕获到这些,我们就有了微调的基础。
怎样定义实时数据的大小?Charlie Hunt和Binu John在他们《Java性能》一书中给出的定义例如以下:
实时数据的大小是由设置在其稳定状态执行应用程序所需的长期消耗对象的堆大小。
有了这个定义,我们在GC日志的打开的情况下就能够相应用程序进行负载測试(-XX:+PrintGCTimeStamps-Xloggc:/tmp/gc.log-XX:+PrintGCDetails)和可视化的日志(比如在gcviewer的帮助下)来确定应用程序达到稳定状态的时间。接下来你所示类似于下图:
我们能够看到。GC进行了minor GC和full GC,有个熟悉的双锯齿形的图形。在第21秒第一次full GC完之后,这个特殊的应用程序看起来已经达到一个稳定的状态了。然而。在大多数情况下,观察到变化的趋势须要10-20次full GC的执行。经过四个full GC,我们能够估算出实时数据大小约等于100MB。
上述《Java性能》这本书表明在一个经典的Java EE应用程序中,实时数据大小和最佳内存配置參数之间有非常强的相关性。这个领域的证据也支持他们的建议:
设置最大堆大小为3-4X(实时数据大小)。
所以。就我们手中应用程序而言,我们应该将-Xmx设置为300M和400M之间进行初始性能測试,并从这里进行调试。
我们对于书上给出的其它建议,建议设置最大的永久代大小为1.2-1.5x(永久代中实时数据大小)以及-XX:NewRatio设置为1-1.5x的(实时数据大小)。眼下。我们正在收集很多其它的数据来确定正相关关系是否存在。可是在那之前,我建议你在配置生存者空间和伊甸园空间时。须要监视到的分配率来作决策。
你可能会问为什么要烦恼这些问题呢?其实,有两个原因让你不须要考虑这个问题:
(1)在写这篇文章的时候,8G内存芯片仅仅售100美元
(2)虚拟化,尤其是大型供应商如亚马逊的AWS使得调试变得更为简单
这两个原因的有效性都是片面的,并且明白地降低了精确调配所需。
可是它们仍然可以将你拉入危急区域。
(1)当有大量内存空间时。你非常有可能会对延迟造成重大影响。8G以上的堆非常easy进行full GC。这将可能停顿超过数十秒。
(2)过度配置时总是会有“稍后调整”的心态。而这“稍后”可能永远就不会再调整了。我见过大量的应用仅仅是由于这个原因。执行在过度配置的环境中。比如,前面所提到的应用程序,我发如今亚马逊EC2上m1.xlarge实例执行成本是每一个实例4200美元/年。若将其转换成m1.small就仅仅需520美元。假设你的部署够大,从业务预算中就能够减少8倍成本,这一点上请相信我。
总结
不幸的是,我依旧看到非常多决策同我十年前被迫做的极其相似,这导致了规划不足或者过度,这两者都是非常差劲的选择。
特别是你甚至不能享受虚拟化带来的优点。
版权声明:本文博客原创文章,博客,未经同意,不得转载。