"我不必担心垃圾收集" - 这是真的吗?
我曾听到我的一些开发者朋友说。"垃圾收集是自动的。所以,我不需要担心这个问题。"第一部分是真的,即在所有现代平台上,"垃圾收集是自动的"--Java、.NET、Golang、Python......但第二部分,即 "我不必担心它"。- 可能不是真的。它是可以争论的,值得怀疑的。下面是我的案例,展示了垃圾收集的重要性。
1.不愉快的客户体验
当垃圾收集器运行时,它会暂停整个应用程序,以标记正在使用的对象并扫除没有活动引用的对象。在这个暂停期间,所有正在运行的客户事务将被停顿(即冻结)。根据你配置的GC算法和内存设置的类型,暂停时间可以从几毫秒到几分钟不等。应用程序的频繁暂停会给你的客户造成卡顿、抖动或停止的效果。这将给你的客户留下不愉快的体验。
2.浪费数以百万计的美元
这是我们发表的一份白皮书,如实解释了企业如何因垃圾收集而浪费了数百万美元。基本上,一言以蔽之,现代应用程序正在创建数千/数百万的对象。这些对象必须不断地被调查,以确定它们是否有活动的引用,或者是否准备好进行垃圾收集。一旦对象被垃圾回收,内存就会变得支离破碎。碎片化的内存必须被压缩。所有这些活动都会消耗*巨大的计算周期*。这些计算周期转化为数百万美元的支出。如果垃圾收集的性能可以被优化,它可以带来几百万美元的成本节约。
3.低风险、高影响的性能改进
通过优化垃圾收集性能,你不仅改善了垃圾收集的暂停时间,而且还改善了整个应用程序的响应时间。我们最近帮助世界上最大的汽车公司之一调整了垃圾收集性能。仅仅通过修改垃圾收集设置**,而没有重构一行代码**,我们就大大改善了他们整个应用程序的响应时间。下表总结了我们对垃圾收集设置所做的每一项改变所带来的整体响应时间的改善。
| 平均响应时间(秒 | 超过25秒的交易(%) | |
| 基准线 | 1.88 | 0.7 |
| GC设置迭代#2 | 1.36 | 0.12 |
| GC设置迭代#3 | 1.7 | 0.11 |
| GC设置迭代#4 | 1.48 | 0.08 |
| GC设置迭代#5 | 2.045 | 0.14 |
| GC设置迭代#6 | 1.087 | 0.24 |
| GC设置迭代#7 | 1.03 | 0.14 |
| GC设置迭代#8 | 0.95 | 0.31 |
当我们开始GC调整工作时,这个汽车应用程序的整体响应时间是1.88秒。当我们用不同的设置来优化垃圾收集性能时,在第8次迭代中,我们能够将整体响应时间提高到0.95秒。也就是说,响应时间提高了49.46%。 同样,花费超过25秒的事务百分比从0.7%下降到0.31%,也就是说,提高了55%。这是在不修改一行代码的情况下实现的重大改进。
所有其他形式的响应时间改进都需要基础设施的改变或架构的改变,或代码层面的改变。所有这些都是昂贵的改变。即使你着手进行这些昂贵的改变,也不能保证应用程序的响应时间的改善。
4.预测性监控
垃圾收集日志暴露了重要的预测性微观指标。这些指标可用于预测应用程序的可用性和性能特征。在垃圾收集中暴露的一个微观指标是 "GC吞吐量"(要阅读更多关于其他微观指标的信息,请参考这篇文章)。什么是GC吞吐量?如果你的应用程序的GC吞吐量是98%,这意味着你的应用程序将98%的时间用于处理客户活动,其余2%的时间用于GC活动。当应用程序出现内存问题时,几分钟后GC吞吐量就会开始下降。像yCrash这样的故障排除工具可以监控 "GC吞吐量",以便在生产环境中出现内存问题之前预测和预报。
5.容量规划
当你为你的应用程序做容量规划时,你需要了解你的应用程序对内存、CPU、网络和存储的需求。研究内存需求的最好方法之一是分析垃圾收集行为。当你分析垃圾收集行为时,你将能够确定平均对象创建率(例如:150 MB/秒),平均对象回收率。使用这些微观指标,你可以为你的应用程序做有效的容量规划。
总结
朋友们,在这篇文章中,我已经尽了最大努力来证明垃圾收集分析的重要性。我祝愿你和你的团队能从极具洞察力的垃圾收集指标中获益。
