上月,由极客邦、InfoQ和听云联合主办2016 APMCon中国应用性能管理大会圆满落下帷幕。会上,Java冠军Martijn Verburg进行了一场Java and the Machine的分享,讨论了为何数据分析相当重要。他有着十多年Java经验,目前是创业公司jClarity的CEO,jClarity是一款采用统计和机器学习来探究性能问题根源的方案。会后,InfoQ还专访Martijn以进一步了解沟通。程序员
JVM堆内存及一种监测方式数组
在讨论Martijn的团队如何进行堆内存监测以前,咱们先回顾下JVM的工做机制。JVM是一种对计算机的抽象行为,是它保证了Java程序的运行。每个运行的Java程序都对应着一个JVM实例。JVM的结构以下图缓存
Java把内存划分红两种:一种是栈内存,一种是堆内存。栈与堆都是Java用来在RAM中存放数据的地方。与C++不一样,Java自动管理栈和堆,程序员不能直接地设置栈或堆。堆内存用来存放由new建立的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。即每个Java应用都惟一对应一个JVM实例,每个实例惟一对应一个堆。网络
自从Java1.3以后,Oracle出台的JRE就包含了一个名为HotSpot的JVM,它将Java的对象按照世代管理并存放在堆的内存中,以期能够更好地管理堆内存中的对象,包括内存的分配以及回收。共划分为三个世代:年轻代、老年代、永久代。永久代(Permanent Generation)则存放的是类的定义和相关元数据。可是在Java 8中该区域已经被移除。专家分析称此举更有利于性能调优。框架
现有版本保留的两个世代为年轻代(Young Generation)和老年代(Old Generation)。年轻代为建立的短时间对象,失效以后很快会被垃圾回收。该区又被划分为Eden和两个Survivor区域。老年代存放的多数为存活时间较长的对象。其中堆的各个区之间的比例分配有默认值,可是能够经过参数指定。垃圾回收GC分为两种Minor GC、Full GC;Minor GC发生频繁,可是仅针对年轻代。机器学习
垃圾回收以后会对JVM形成必定影响,年老代的占用空间曲线以下图:工具
上图来自jClarity对堆的年老代占用空间监测图,jClarity是一款Java的性能监测工具,由Martijn、另外两位资深Java专家和一位机器学习工程师共同实现。Martijn分享了jClarity如何进行堆内存的监测他首先列举了垃圾回收以后,一般状况下堆内存中的老年代(Tenured/Old Generation)的内存占用曲线,通常而言,会前后发生两个陡然增长的高峰。性能
基于以上现象的信息, Martijn和他的团队开展了他们的性能监测方案。Martijn他们采起的作法是先收集尽量多的点,而后只保留老年代的数据,对垃圾回收形成的两个脉冲式波峰进行了过滤,这时再对这些真正的数据点进行建模抽象,最后保留出了一条曲线。学习
这条曲线就是对监测的Java程序内存的变化趋势,该曲线会以50Mb/小时的速率增加,据此推测出什么时候发生内存泄露。jClarity还有不少其余功能,相比于传统的指标统计方式,Martijn称团队产品的特色在于:高级统计+机器学习。大数据
Java和JVM面临怎样的困境?
Martijn还分享了他对Java现状和JVM性能调优的担心和思考,他认为如今Java和JVM面临下面五个问题:
程序只能写一次,可是却要在各类地方跑
这意味着Java须要解决来自各方面的差别:
CPU的差别——何时能够放入缓存中呢?何时能够被从新排序呢?
文件系统的差别——不一样操做系统对文件的符号连接有不一样机制
显示设备的差别——硬件更新速度很快,几乎没法追上
原生库支持的差别——很难存在全部的原生库皆一致的状况
操做系统线程管理的差别——线程的规划方式很不相同
此外,面对正在迅速发展AR、VR,Java缺乏真正的GPU支持,这一样是一个短板。模型对存储的强需求
JVM太谨慎了,他总想作对的事情,可是为此不得不在性能上的妥协。锁机制增强了正确性,可是在性能上付出了巨大的代价。
锁机制决定了Java序列化的工做区。由于Java对象序列化不只保留一个对象的数据,并且递归保存对象引用的每一个对象的数据。能够将整个对象层次写入字节流中,能够保存在文件中或在网络链接上传递。利用对象序列化能够进行对象的"深复制",即复制对象自己及引用的对象自己。序列化一个对象可能获得整个对象序列。结合利特尔法则(Little's law)和阿姆达尔定律(Amdahl’s law),这种方式影响到了并行存储的性能。垃圾回收机制下的扩展性
JVM须要维护活的对象,这意味着:堆须要更大空间以存放更多的对象;垃圾回收机制须要花时间去辨认哪些是活的对象;在垃圾回收过程当中须要耗费时间进行堆的维护。
其次,Java中没有值类型(value type 和reference type的区别),没有结构体:这形成了大量低效能的对象建立。容器和虚拟化的支持
Java无法获取虚拟化数据。Java和JVM的思考模式是创建在物理裸机上的,信息缺失的状况下会进行一些错误选择。而且,没有对Docker等容器技术的直接支持,这是新时代的另外一个短板。
关于Java和JVM性能调优的思考
除了上述的总体层面的挑战以外,Java的性能自己又很难监测。必须结合其余的指标来间接把控:CPU,内存;接口I/O,网络I/O;虚拟化和容器化等。但是一旦得到了这些指标,又带来了大数据的问题。由于咱们盲目地收集了过多的数据,这形成了巨大的性能损害,由于收集、传输、存储每一个过程都是一种消耗。
要记住目的是分析得到信息,而不是收集指标。可是从指标数据到提炼出有用信息很难,Martijn认为要作好性能调优须要明白规律和原理(如上文所说起的Little's law和Amdahl’s law),理解硬件、操做系统、Java工做原理还要读懂代码,而且已经有了基于大量数据的分析经验。
Martijn认为将来性能监测的趋势是高级统计和机器学习方式的结合,这种模式将取代传统的单纯指标采集模式。
对话Martijn
InfoQ:一般来讲,JVM层面的APM工具并不适用于生产环境。那为何您称jClarity能够?
Martijn:与其余工具相比,首先在JVM层面上咱们获取更少的数据。 jClarity之因此能够更少地获取,是由于咱们采用了机器学习的办法,辨别除了哪些才是真正有用的数据,咱们称之为“信号”,余下的数据咱们称之为噪声。在收集数据过程当中,一旦检测噪声,咱们马上对过滤。
其次咱们还会尽量避免从JVM自己获取数据,取而代之从JVM的日志中(如GC日志、safepoint日志)等获取数据。目前咱们还在和Google合做,在尝试怎样从JVM以外,得到更多的信息。可是,整体而言,jClarity用于生产环境是没有问题的。
InfoQ:为何还要收集JMV的日志以外的数据呢?
Martijn:由于JVM日志并不能给咱们足够的信息。你能够从JVM日志中得到,或者经过JMX接口。不过,你也能够经过设定一个Java或者原生的agent来得到更特定的信息;但这是一种太重的作法,一般而言并不推荐。不少人包括Oracle在内都意识到了这个问题,可是彻底解决有待时日。
InfoQ:数据收集的过程是否对用户来讲是透明的呢?是否支持ASM字节码织入技术呢?
Martijn:是的。底层的数据,咱们不只仅从Java中得到,还会从操做系统中获取。好比,当用户在Linux上运行,那么他还会看见收集到的CPU、内存使用率等信息。
对于有特殊需求的用户,他们是能够采用ASM,此外咱们也提供一个开发阶段使用的库,可是建议用户当心使用,由于很容易会产生操做不当。
InfoQ:数据收集以后,jClarity根据机器学习出来的成果进行了处理,可否和咱们分享下机器学习的事情?
Martijn:在我被许可的范围内,由于机器学习是咱们的机密模块。不过我能够分享这里很是重要的一点:咱们有大量多环境的用户数据,用户们的程序也是多种多样,如网页程序、视频流程序等;咱们会施加不一样的网络压力,这样咱们获得了数据训练集。这些数据集是专家人工操做产生的。同时在实时收集处理数据的时候,咱们也会进行机器学习。好比发现Java性能受到影响,机器学习认定最重要一个因素就是GC垃圾回收,那么接下来就是调查GC;若是GC没有问题,那么就会在机器学习成果的指引下开始下一个因素的勘察。整体而言,机器学习的决定了发生问题时排查的路径。
机器学习这部分的研发工做咱们作了两年,也很感谢这些用户为咱们付费而且赞成咱们这样作。咱们的一些用户拥有超大规模,这种状况下,已经没法期望人工对数据进行分析;因此对于咱们来讲,机器学习是惟一的出路,惟一的方式可让咱们继续支持用户。
InfoQ:APM工具的挑战有哪些?
Martijn:首先是IT环境复杂性的加重。你的代码再也不跑在你本身的机器和环境中,你没法作到100%肯定你的程序和代码是怎样被管理的。另一个挑战就是网络是不稳定的。在有线光纤专用网络上,你不须要和其余人共享;可是在公用云上,网路流量徒增的状况时有发生,开发人员不得不在代码层面上面对这个挑战,APM工具也必须理解并迎面这个问题。目前,尚未哪一个APM工具能够胜任这两个挑战,因此目前这仍是一个很是有趣有待研究的领域。
InfoQ:您在演讲中有提到,Java创立之初硬件并无今天这样复杂,那么是否是说Java已经再也不适合今天了呢?你认为Java语言的独特魅力在哪里呢?
Martijn:“Java将死”的留言每一年都有。Java语言这么多年,常常遇到新兴语言的挑战,可是新兴语言很快就会发现本身也处于一个相似的局面。我认为Java依然是一个合适的语言,JVM正在尝试在各类状况下都作到最好。咱们能够看到Go、RUST语言变得愈来愈火,可是Oracle正在很是努力地攻克这点,包括更频繁地发布Java,也很想快速地跟上包括支持GPU、其余新型硬件设备等。因此说挑战是有的,可是使人高兴的是不少大公司都愿意继续努力提升Java。我但愿Java社区能够更开放些,能够欢迎更多的公司参与,好比阿里巴巴,阿里巴巴多是全球上最大的重度Java研发群。
Java的魅力在于易写性、强可读性。不像如今的一些语言,你不须要严格地按照某种规范来写代码。就算代码写完五年以后,新来的人依然能够读懂代码。还有就是Java丰富的框架和库。甚至这些框架和库的魅力能够和Java语言自己相媲美。
https://yq.aliyun.com/articles/145758?utm_content=m_26867