我已经花了几个月的时间考虑审查有关性能调优,JVM,Java中的GC,Mechanical Sympathy等主题的文章和视频的缓存,并最终花了点时间–也许这就是重点我什么时候需要做我的智力进步!
感谢Attila-Mihaly给我提供了为其年度时事通讯Java Advent Calendar撰写帖子的机会,因此对各种Java相关主题进行评论非常合适! 视频和文章的选择纯粹是随机的,并且基于我了解的顺序。 我隐藏的议程是主要通过他们来理解和扩展我自己的知识,同时与他人分享任何见解。
我将介绍Attila Szegedi(1个演讲)和Ben Evans(2个演讲)的三篇演讲评论。 他们谈论Java性能和GC的主题。 Attila的首次演讲涵盖了他在Twitter上担任工程师的丰富经验-因此,其大量信息来自生产系统领域的现场经验。 在他的演讲中,用薄物体代替胖物体是流行语之一。
Ben在他的两个演讲中深入讨论了性能,JVM和GC。 他指出了人们对性能,JVM和GC的误解,以及人们在生产中未启用某些运行时标志的事情。 基础机械的工作原理,为什么以其工作方式工作,机械的效率如何,如何最好地做而不是为了从中获得好的吞吐量呢?
在这里,我讲解我的观点,我决定从Attila Szegedi的演讲开始,因为我非常喜欢这个标题.....
演讲时的Attila在Twitter上工作,他从中学到了许多有关JVM和Java语言本身的内部知识– Twitter是一个组织,实际上需要进行调整,优化JVM,低延迟。
他涵盖了有趣的主题,例如:
- 延迟的贡献者
- 完成的代码尚未准备好用于生产
- 性能调整的区域(主要是内存调整和锁争用调整)
- 内存占用调整(OOME,效率低下的调整,FAT数据)
- FAT数据-由他创造的新术语,以及如何解决由它产生的问题(非常深入和有趣)-了解有关Java / JVM语言中数据类型的字节分配。
这些建议之一(包括陷阱)是一些深入的潜水主题,例如压缩对象指针。 正如JVM分析器所揭示的那样,Scala 2.7.7中的某些类型效率很低。 不要使用Thrift –因为它不是低延迟的朋友,因为它们很沉重–每个对象增加52到72字节的开销,不支持32位浮点数,等等…注意线程局部变量–坚持使用并且使用了比预期更多的资源。
在表演三角上,Attila分享了他对这一概念的见识。 GC是JVM的最大威胁。 老一代使用ConcCollector,而新一代使用STW流程,并征集了许多吞吐量和低暂停时间的收集器。
通过利用“自适应大小调整”策略来改进GC,并为其制定目标。 使用带有或不带有自适应策略的吞吐量收集器,并对结果进行基准测试。 他带领我们完成了各种-XX:+ Print ...标志,并说明了其用法。 保持碎片少并避免GC完全停止。 有关GC工作原理的详细信息,以及如何改进GC(调整新旧基因)。
与GC不相关的延迟–线程协调优化。 当使用线程来改善延迟时,可以使用屏障和半屏障;在使用Atomic值和AtomicReferences时,可以使用一些技巧。 Cassandra平板分配器–帮助提高效率和性能–无需编写自己的内存管理器。 Attila不再是“软参考”的粉丝–尽管理论上很棒,但实际上却不行,但需要更多的GC周期来清除它们!
结论:
经常了解您的代码,这可能是问题的根源-框架可能多次成为性能问题的原因。 如果人们知道如何最好地利用开发环境的数据结构的基本构建块,则可以做很多事情来降低所编写程序的性能。 要保持最佳的吞吐量并从JVM中获得最佳性能,这是一项艰巨的任务。
-建议观看视频,内容比上面的摘要要多得多-
Ben在本文中介绍了有关Java,其性能,GC等的古老神话和假设……涉及的领域包括:
1) Java速度慢; 2)一行Java意味着孤立的任何事物; 3)微型基准意味着您认为它可以做什么,
4)算法缓慢是导致性能问题的最常见原因; 5)缓存解决了所有问题; 6)所有应用都需要关注世界停止状态; 7)手动滚动对象池适用于各种应用, 8) CMS总是比Parallel Old,GC更好的选择GC )9)增加堆大小将解决您的内存问题
- 在许多情况下,JIT编译的代码与C ++一样快
- JIT编译器甚至可以在分析数据的基础上优化掉无效和未使用的代码。 在JRockit之类的JVM中,JIT可以分解对象操作。
- 为了获得最佳结果,请不要过早优化,而要纠正性能热点。
- 理查德·费曼(Richard Feynman)曾经说过:“第一个原则是,您切勿愚弄自己-并且您是最容易愚弄的人” –在编写Java微基准测试时要牢记的一点。
人们对Java的想法是观点,但与现实相反。 基本上是建议群众重新审视思想,根据纯粹的事实而不是假设或旧的信念做出结论。
- 与算法相比,GC,数据库访问,配置错误等都可能导致应用程序运行缓慢。
- 测量,不要猜测! 使用经验生产数据来发现性能问题的真正原因。
- 不要只是添加一个缓存以将问题重定向到其他地方并增加系统的复杂性,而是要收集基本的使用情况统计信息(未命中率,命中率等)以证明缓存层确实在增加价值。
- 如果用户没有抱怨,或者您不在低延迟堆栈中,则不必担心STOP-THE-WORLD暂停(大约200毫秒,具体取决于堆大小)。
- 对象池非常困难,并且仅在GC暂停不可接受且调优和重构的智能尝试无法将暂停减少到可接受的水平时才应使用。
- 检查CMS是否是正确的GC策略,首先应确定Parallel Old的STW暂停是不可接受的,无法进行调整。 Ben强调要确保所有指标都是在等同于生产的系统上获得的 。
- 在更改堆大小或调整其他参数之前,了解对象分配和生存期的动态至关重要。 不加估量行事会使事情变得更糟。 来自垃圾收集器的权属分配信息在这里尤为重要。
结论:
由GC子系统具有用于调谐和用于产生数据,以指导调谐,然后使用一个工具来分析日志令人难以置信的潜力-无论是手写脚本和某些图形的产生,或作为(开源)的可视化工具,例如GCViewer 或商业产品 。
人们对GC的理解有误解或不足。 它不仅是Mark&Sweep。 如今,许多运行时都具有GC! 两种思想流派– GC和参考计数! 与需要高精度的机器相比,人类会犯错误。 True GC是Java率先开发的,效率极高,引用计数非常昂贵。
分配列表是所有对象都源自的列表。 如果不停止应用程序,就无法在正在运行的实时应用程序的任何给定时间点上获得运行中对象的所有对象的准确图片,这就是我们拥有STW(停止世界)的原因!
GC的黄金法则
- 必须收集所有垃圾(敏感规则)
- 绝不能收集活动物体
(技巧:但是他们永远不会平等地创造)
热点是C / C ++ / Assembly应用程序。 堆是具有不同内存池(Young Gen,Old Gen和PermGen池)的连续内存块。 对象由应用程序(变量)线程创建,并由GC删除。 由于GC始终导致应用程序运行缓慢。
PermG –不理想,在Java 8中消失了(已知问题:导致OOME异常),由堆(本机内存)之外的Metaspace代替。
GC基于“弱世代假设”(即对象过早死亡或过时死亡),是通过经验研究发现的。
保有期限阈值是您移至Old Gen(保固空间)之前可以生存的GC数量。 JavaFX与jdk7u6及更高版本捆绑在一起。
用Java编写的JavaFX Memory Visualizer的源代码替换了使用FlexML(FXML)编写的Flash版本– https://github.com/kittylyst/jfx-mem 。 关于如何用一种不错的编程语言FlexML编写程序的广泛解释–将构建器模式与类似DSL的表达式结合使用。 该程序模拟GC的工作方式以及如何在不同的池中创建,销毁和移动对象。
强制性标志列表,对性能没有任何影响
- 详细:gc
- Xloggc:<路径文件>
- XX:+ PrintGCDetails
- XX:+ PrintTenuringDistribution
上面记录了有关正在执行的应用程序和GC的所有信息。 还介绍了基本的堆大小调整标志。 自从JDK的最新版本以来,将堆标志设置为相等就不再适用。 另外,GC和VM有200多个标志,其中不包括所有未记录的标志。
GC日志文件对于后处理很有用,但有时记录不正确。 MXBeans会影响正在运行的应用程序,但不会提供比日志文件更多的信息。
GC日志文件具有通用格式,可提供有关分配更改,占用率,任期信息,收集信息等信息的信息,– GC日志文件格式爆炸式增长,并且工具不多。 许多免费工具涵盖了某种仪表板,例如显示各种与GC相关的指标的输出,而商业版本通常具有更好的方法和有用的信息。 过早推广 –在创建新对象的压力下,对象直接从YG移到OG,而无需经过Survivor空间。
使用工具,进行测量,不要猜测!
结论:
了解事实并找出细节(如果不知道但不要猜测或假设)。 错误的概念有时会导致假设和对JVM和GC进程的错误理解。 不要只是更改标志或使用工具,不知道为什么以及它们做什么。 例如,打开GC日志记录(启用适当的标志)不会对JVM的性能产生明显影响,但从中长期来看是一个福音。
—强烈建议您观看视频,其内容比上面的提要要多得多,Ben以一种最简单的方式解释了GC,其中涵盖了许多重要的细节—
由于查看所有此类视频和文章不切实际,因此在下面的链接中提供了许多视频和文章以供进一步研究。 在许多情况下,我已经解释或直接引用了作者为保留信息和希望传达的意思而不得不说的话。 2013年12月19日 ,此博客文章的后续文章将出现在标题为(第2部分,共3部分)的同一空格内:有关性能调优,JVM,Java中的GC,Mechanical Sympathy等的文章和视频的摘要 。
有用的资源
- 您的GC日志对您说的是G1GC版– 幻灯片 – 视频
- Java应用程序性能调优的原理
- 表演特别兴趣小组的讨论 –由Richard Warburton主持 (视频)
- 缓存: @RichardWarburto提供的“更有效地理解,衡量和使用CPU缓存” (视频和幻灯片)
- 关于原子I / O操作的文章(Linux)
- 有关Azul Zing,低延迟GC和OpenJDK的文章和演示文稿 (视频和幻灯片)
- Martin Thompson的无锁算法实现终极性能
- Performance Java User's Group –“面向想要将系统推向新高度的专业Java开发人员”
- 优化Google的仓库规模计算机:NUMA体验 – Univ的作者。 Cal(SD)和Google的资料!
- MegaPipe:多位作者的可扩展网络I / O的新编程接口 !
- 每个程序员应该了解的关于内存的知识Ulrich Drepper
- 内存壁垒:针对软件黑客的硬件视图 – Paul E. McKenney(Linux技术中心– IBM Beaverton)
- Vanilla #Java了解Core Java的真正工作原理可以帮助您编写更简单,更快的应用程序 ,作者Peter Lawrey
- 通过Kirk Pepperdine 调整线程池的大小
翻译自: https://www.javacodegeeks.com/2013/12/part-1-of-3-synopsis-of-articles-videos-on-performance-tuning-jvm-gc-in-java-mechanical-sympathy-et-al.html