性能调优、虚拟机、垃圾回收、软硬件协调相关文章和视频 — Part1
本文由 ImportNew - 顾星竹 翻译自 javacodegeeks。如需转载本文,请先参见文章末尾处的转载要求。
ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的 Java开发 小组。参与方式请查看小组简介。
最近好几个月,我一直在考虑整理性能调优、Java虚拟机(JVM)、Java垃圾回收(GC)、软硬件协调(Mechanial Sympathy)等主题的文章和视频,最终我决定花时间去做——在我做这件事的时候也许正标志着智力提升的转折点。
感谢Attila-Mihaly给我机会为他的年刊Java Advent Calendar 写下这篇后记。为此我阅读了一系列好符合本文要求的相关Java话题。本文对文章和视频的选择完全是随机的,按照我了解它们的先后进行排序。我的另一个目的是通过这项工作理解和拓宽自己的知识域,同时与他人分享。
本文的内容包含三次演讲,一次Attila Szegedi的演讲,两次Ben Evans的演讲。这些演讲详细地讨论了Java性能和GC方面的主题。Attila的演讲包含了很多他在推特做工程师的经验——所以有很多信息是超出生产系统领域日常经验的。多使用小对象(thin object)而不是富对象(fat object)是他的口头禅。
Ben在他的两次演讲中深度探讨了性能、JVM和GC。他指出了人们对性能,JVM和GC的误解,人们在产品中没有使用特定的运行时参数(run-time flag)。机器底层的工作方式如何?为什么按照这样的方式工作?为了得到最好的输出,应该做什么和不做什么?
下面是我的评论,我决定从Attila Szegedi的演讲开始,因为我挺喜欢这标题……
1、我所知道的关于JVM性能调优的那些事儿
—— Attila Szegedi @推特(视频&幻灯片)
Attila进行这次演讲时正在推特工作,在那里他学到了很多JVM内部实现机制和Java语言本身的知识——在推特,JVM调优、低延时都是标准实践。
他谈到了下面这些有趣的话题:
- 延迟产生的原因。
- 已完成的代码不能直接上线。
- 需要性能调优的领域(主要是内存调优和锁竞争机制的调优)。
- 内存调优(内存溢出异常 “OOME”、低延时优化、FAT数据)。
- FAT数据——这是Attila创造的一个新术语,讨论了如何解决由FAT数据引发产生的问题(非常深入而且有趣);学习了在Java或JVM语言中各种数据类型的字节分配。
他还讨论了一些比较深入的话题,例如建议压缩对象指针(这里包含了一个陷阱);通过JVM分析工具发现,Scala 2.7.7中有一些类型是低效的;不要使用Thrift——因为它不是低延时的(low-latency),它们的开销很大——每个对象的开销增加了52到72字节,而且不支持32比特的浮点数;小心本地的线程——它们占用的资源比预期得更多。
译注:Apache
Thrift,一个可伸缩的跨语言服务框架。
Attila分享了他对性能三角(Performance triangle)概念的深入理解:GC是JVM最大的威胁;旧代(也称年轻代)使用ConcCollector,新代(也称终身代)使用SWT进程;包含一系列吞吐量(throughput)、低延时的Collector。
通过大小自适应策略来提高性能是GC的改进目标。通过高吞吐量Collector配合)自适应策略(也可以不使用,用标准检查程序 “benchmark”测试这些结果,他带领我们游历了一系列 –XX:+Print等参数(flag)并说明了它们的作用。保持碎片数位于较低水平并避免GC完全停止。这其中包含许多GC工作的技术细节以及如何提高GC性能(同时优化新代和旧代)。
与GC无关的延迟——线程协调优化。在使用线程时可以通过设置障碍(译注:通过避免竞争)减少延迟——可以配置原子值(Automic Value)和原子引用(Automic Refernce)一起使用;使用Cassandra slab allocator(译注:Slab
Allocator,一种内存管理机制)可以帮助提高性能和效率——无需自己编写内存管理器。Attila已经不再是“软引用,SoftReference”的粉丝——理论虽好但不实用,GC需要更多的周期才清除软引用对象。
结论
经常去了解你的代码,它们往往是问题的根源所在——框架常常导致性能问题。如果深谙如何更好地使用构成开发环境的基础模块数据结构,那么提高性能还有很多事情可以做。针对JVM维持最佳吞吐量和最佳性能是一个非常困难的游戏。
— 建议观看视频,有很多上文概要没有覆盖到的内容 —
2、Java性能的9大谬误
—— Ben Evans(博客)
在这篇文章中Ben破除了一些Java性能、GC方面的神话和假设。涵盖的内容包括:
- Java很慢。
- 每行Java代码的功能都是孤立的。
- 一个微基准测试(micro-benchmark)验证的内容会和你想象的一样。
- 算法通常是导致性能问题的主要原因。
- 缓存能解决所有问题。
- 所有应用都需要考虑GC完全停止(Stop-the-world)问题(译注:当垃圾收集没有结束前对于外部的请求是不会进行响应的,直到收集完毕应用才会继续响应请求)。
- 手工对象池(Hand-rolled Object Pooling)适合绝大部分应用。
- 在GC中,CMS比并行旧代收集器总是一个更好的选择。
- 增加堆的大小会解决内存问题。
译注:根据Ben的解释实际的情况是:
- JIT编译的代码很多情况下和C++一样快。
- JIT编译器可以优化无用以及未使用代码,甚至在做数据分析(Profiling)时也是如此。在JRockit这样的JVM中,JIT可以分解对象的操作。
- 为了获得最佳结果,不要过早优化,而应该修正潜在的性能问题。
- Richard Feynman曾经说过:“第一原则是不能欺骗自己,而自己往往是最容易被欺骗的。”——在编写Java微基准测试时须牢记这句话。
问题在于人们心中关于Java的看法与事实相反。建议大家重新思考自己的看法,然后基于事实而不是假设或过去的观点得出自己的结论。
- GC、数据库存取、错误配置等与问题算法一样会使应用变得缓慢。
- 估算,而不是猜测!使用实际的生产数据来发现性能问题的真正原因。
- 不要通过增加缓存把问题转移到别的地方,这样会增加系统的复杂性。要收集基本的数据使用情况(未命中率、命中率),以此证明实际运行中用到了缓存。
- 如果用户没有抱怨或者没有用低延迟栈(Low-latency Stack)—— 不必担心GC的Stop-the-world暂停问题(根据堆的大小而有所不同,大约暂停间隔是200毫秒)。
- 对象池使用起来非常困难,只有GC引起的暂停不可接受时才可以使用。智能调优和尝试重构也不能在可接受的程度上减少GC暂停时间。
- 请确认GMS是否是最适合你的GC策略,首先确认由并行旧代收集器引起的STW(Stop-the-world)问题是不可以接受并且不可优化的。Ben在这里要强调的是:要确保所有数据都从与生产系统匹配的环境中获得。
- 在改变堆内存或其他参数之前,正确理解对象的动态分配和生命周期是很有必要的。没做调查就开始行动只会使事情更糟。在这里,获得GC的分布信息非常重要。
结论
GC子系统有着令人难以置信的优化潜能,可以在生产数据指导下进行调优;可以使用工具来分析log——不管是手写的脚本或工具生成的图形;可以利用可视化工具,比如(开源的)GCViewer 或者商业工具。
3、可视化Java垃圾回收(GC)——
Ben Evans(视频&幻灯片)
通常人们对GC会产生误解或者理解上有欠缺。GC并不仅仅是标记对象和清理对象。如今,很多运行时也具备了GC!现在有两种思想流派——GC和引用计数!与机器运行时要求的高精度相对的是,人类往往会犯错。真正的GC是难以置信的高效的,而在Java中引用计数的开销很大。
所有的对象都来自分配列表。在不停止应用的情况下,你没法得到运行中的应用在某个特定时刻所有对象的精准视图,这就是为什么会有STW(Stop-the-world)!
GC黄金定律
- 必须回收所有垃圾(敏感规则)。
- 必须不能回收任何活动对象。
(诀窍:任何对象都不会平等创建)
HotSpot是C、C++、汇编应用程序。堆是具备不同内存池的相邻内存块——新代、旧代和永久代内存池。对象由应用(突变体 mutator)创建,由GC移除。由于GC的存在,应用速度不会很慢。
PermG——不可取,在Java 8中被移除了(已知问题:会引发OOME异常),在堆外由Metaspace取代了(本地内存)。
GC是基于“弱代假设(Weak Generation Hypothesis)”——由实证研究发现,对象死于新代或旧代。
Tenuring threshold是指你转移到旧代(Tenuring空间)之前留存的GC数目,JavaFX与jdk7u6及更高版本绑定。
JavaFX内存可视化器使用Java编写源码,取代了之前使用FlexML(FXML)编写的Flash版本——https://github.com/kittylyst/jfx-mem。关于如何使用FlexML编写程序有着广泛的解释。FlexML是一个很好的编程语言,它结合了构造者模式和类似DSL(领域专用语言)的表达式。这个程序为GC如何工作、如何创建、销毁对象并在不同的对象池之间转移建立了模型。
下面列举了必须的命令参数,不会对性能产生任何影响:
- verbose: gc
- Xloggc:<pathtofile>
- XX:+PrintGCDetails
- XX:+PrintTenuringDistribution
运行应用和GC所需要的所有信息在上文都提到了,并且还包含了设置基本堆大小的参数。设置堆参数进行匹配在新版本的JDK中已不再适用了。此外,还有200多个GC和VM的参数,这还不包括文档中没有提及的参数个数。
GC的工作日志文件在后续处理中很有用,但有时候记录的内容并不完全正确。MXBeans会对运行中的程序有影响,但是比起工作日志文件并没有提供更多的信息。
GC的工作日志文件采用的是一般格式,提供了诸如内存分配变化、内存占用、占用信息、集合信息等等。GC的log文件格式呈现爆发式增长,然而没有很多相关的支持工具。许多免费的工具包含GC的一些指示信息,比如各种统计数据等等;商业工具会提供更好的方法和更有用的信息。对象早熟现象(premature promotion)——在创建对象的压力下,对象在不经过残存空间(Survivor spaces)直接从新代过渡到旧代。
使用工具测量,不要猜测!
结论
当不知道一件事情时,去了解事实找到细节,而不是猜测和假设。错误的设想已经多次导致对JVM和GC流程的假设和错误理解。不要仅仅改变参数(flag)或者使用工具,而是要去了解为什么这么做,以及它们究竟做了什么。例如,虽然切换GC工作日志(使用恰当的参数)看不到JVM性能上的显著提高,但是中长期来看会收获良好的效果。
— 强烈建议观看视频,有很多上文没有覆盖到的内容。Ben用最简洁的方式解释了GC,包含了很多重要细节 —
翻阅所有这类的视频和文章是不实际的,所以我选出了一些把链接贴在下文中以便深入学习时提供参考。本文已经转述或者直接引用了这些文章中的内容以及作者想要传递的信息。
有用的资源
- 你的GC日志告诉了什么,G1GC版本(英文) — 幻灯片 — 视频
- Java应用性能调优原则(英文)
- 性能特别兴趣小组讨论(英文) —
Richard Warburton (视频) - 理解、测量,让你的CPU缓存更高效(英文) —
@RichardWarburto (视频和幻灯片) - Linux
原子IO操作(英文) - Azul Zing、低延时GC和OpenJDK文章及演示(英文) (视频和幻灯片)
- 无锁算法终优化(英文) —
Martin Thompson - 性能用户组
– “致力于提升系统性能的Java专家”(英文) - 优化Google
Warehouse规模计算机:NUMA体验(英文)— 作者来自加州大学戴维斯分校和Google! - MegaPipe:一个新的可扩展网络IO编程接口(英文) —
多位作者合著! - 每个程序员都应当知道的内存知识(英文)—
Ulrich Drepper - Memory界限:软件黑客眼中的内存(英文) —
Paul E. McKenney (Linux技术中心 — IBM比佛顿) - Vanilla #理解Core Java工作机制,助你编写更简单、快速的应用(英文) —
Peter Lawrey - 线程池调优(英文) —
Kirk Pepperdine - 原文链接: javacodegeeks 翻译: ImportNew.com- 顾星竹
译文链接: http://www.importnew.com/8147.html
性能调优、虚拟机、垃圾回收、软硬件协调相关文章和视频 — Part1的更多相关文章
- java虚拟机学习-JVM调优总结-垃圾回收面临的问题(8)
如何区分垃圾 上面说到的“引用计数”法,通过统计控制生成对象和删除对象时的引用数来判断.垃圾回收程序收集计数为0的对象即可.但是这种方法无法解决循环引用.所以,后来实现的垃圾判断算法中,都是从程序运行 ...
- JVM调优-Java垃圾回收之分代回收
为什么要进行分代回收? JVM使用分代回收测试,是因为:不同的对象,生命周期是不一样的.因此不同生命周期的对象采用不同的收集方式. 可以提高垃圾回收的效率. Java程序运行过程中,会产生大量的对象, ...
- spark性能优化-JVM虚拟机垃圾回收调优
1 2 3 4
- Tomcat和Java Virtual Machine的性能调优总结
就算生不逢时,也该理解理解了.已经在Java界快混迹3年了,对于一些性能调优的话题我是一直插不上嘴,只是针对昨晚看到的一篇性能调优的文章,我忍不住了. Tomcat性能调优: 找到Tomcat根目录下 ...
- Tomcat和JVM的性能调优总结
Tomcat性能调优: 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创 ...
- 《Tomcat和JVM的性能调优你真的学会了吗?》总结篇
Tomcat性能调优: 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创 ...
- 一份 Tomcat 和 JVM 的性能调优经验总结!拿走不谢
Tomcat性能调优 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创建 ...
- 性能优化 | Tomcat和JVM的性能调优总结
Tomcat性能调优: 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创 ...
- Tomcat 和 JVM 性能调优总结
Tomcat性能调优: 找到Tomcat根目录下的conf目录,修改server.xml文件的内容.对于这部分的调优,我所了解到的就是无非设置一下Tomcat服务器的最大并发数和Tomcat初始化时创 ...
- 一文带你深入了解JVM性能调优以及对JVM调优的全面总结
目录 JVM调优 概念 基本垃圾回收算法 垃圾回收面临的问题 分代垃圾回收详述1 分代垃圾回收详述2 典型配置举例1 典型配置举例2 新一代的垃圾回收算法 调优方法 反思 一.JVM调优的一些概念 数 ...
随机推荐
- layui的各模块的基本用途是什么?
Layui 是一个流行的前端UI框架,提供了多个模块,每个模块有不同的功能和用途.以下是 Layui 的一些主要模块以及它们的基本用途: 核心模块(layui): Layui 的核心模块包含了一些核心 ...
- android 播放视频页面黑屏,且报错:Couldn't open 'xxxxxx' java.io.FileNotFoundException: No content provider:
原因为,activity的顶部布局,VideoView设定了android:background="@color/bg_black"去掉就可以了 之前跑着都正常,改了UI后就没有去 ...
- jstack排查cpu占用高的步骤
通过jstack排查cpu占用高的问题 1.通过top命令找到cpu占用高的应用程序进程 2.通过top -H -p pid查看该应用中占用CPU高的线程. 3.通过printf "%x\n ...
- C++ 性能反向优化——用哈希表unordered_map消除if else导致性能降低。
从代码整洁的角度考虑,对于不同的值将调用相同参数的不同函数,我们通常可以通过建立从值到对应函数指针的哈希表,从而将if else消除.但实际可能使性能更低,以下是测试例子. 原因在于,if else分 ...
- EF Core报错“Format of the initialization string does not conform to specification starting at index 0.”
问题分析: 今天在EF Core数据库迁移的过程中无意中发现此错误,我的项目仅仅复制黏贴了配置文件而已,自此发现是数据库配置文件json在作祟. 对比了下发现是.json文件没有被设置"复制 ...
- 【论文解读】transformer小目标检测综述
一.简要介绍 Transformer在计算机视觉领域迅速普及,特别是在目标识别和检测领域.在检查最先进的目标检测方法的结果时,我们注意到,在几乎每个视频或图像数据集中,transforme ...
- CSS – ellipsis and line-clamp
前言 CSS 很早就有 build-in 方案 for 省略号 ellipsis 了. 但是只能 one line, 遇到多行的时候只能用 JS. 后来出了 line-clamp 终于把 multip ...
- 使用 fabric.js 开发移动端 H5 图片编辑器
大家好,我是开源图片编辑器的 https://github.com/ikuaitu/vue-fabric-editor 的作者,它是一款基于 PC 版本的开源图片编辑器. 最近很多开发者咨询,是否可以 ...
- 暑假集训CSP提高模拟5
听好了: 7 月 22 日,比样的学长就此陷落.每个陷落的学长都将迎来一场模拟赛,为这些模拟赛带来全新的题面. 你所熟知的一切都将改变,你所熟悉的算法都将加诸比样的考验. 至此,一锤定音. 尘埃,已然 ...
- Java远程连接服务器实现文件上传下载及目录操作
详情请阅读原文 在其基础之上做了进一步的封装 <!-- https://mvnrepository.com/artifact/com.jcraft/jsch --> <depende ...