jvm 性能

HotSpot是我们众所周知和喜爱的JVM,是Java和Scala汁流淌的大脑。 多年来,许多工程师对其进行了改进和调整,并且每次迭代时,其代码执行的速度和效率都接近于本机编译代码。

JIT(“及时”)编译器是其核心。 该组件的唯一目的是使您的代码快速运行,这是HotSpot如此受欢迎和成功的原因之一。

JIT编译器实际上是做什么的?

在执行代码时,JVM会收集有关其行为的信息。 一旦收集了有关热方法的足够统计信息(默认阈值为10K调用),编译器就会启动,并将该方法的与平台无关的“慢”字节码转换为自身的优化,精简,平均编译版本。

一些优化是显而易见的:简单的方法内联,清除死代码,用本机数学运算替换库调用等。请注意,JIT编译器不会就此停止。 这是它执行的一些更有趣的优化:

分而治之

您使用以下模式多少次:

StringBuilder sb = new StringBuilder("Ingredients: ");for (int i = 0; i < ingredients.length; i++) {if (i > 0) {sb.append(", ");}sb.append(ingredients[i]);
}return sb.toString();

也许这个:

boolean nemoFound = false;for (int i = 0; i < fish.length; i++) {String curFish = fish[i];if (!nemoFound) {if (curFish.equals("Nemo")) {System.out.println("Nemo! There you are!");nemoFound = true;continue;}}if (nemoFound) {System.out.println("We already found Nemo!");} else {System.out.println("We still haven't found Nemo : (");}
}

这两个循环的共同点是,在这两种情况下,循环都会做一件事一段时间,然后从某个角度开始做另一件事。 编译器可以发现这些模式,并将循环拆分为多个案例,或“剥离”多个迭代。

让我们以第一个循环为例。 if (i > 0)行在一次迭代中以false开头,则从那一点开始始终为true 。 那么为什么每次都要检查情况呢? 编译器将编译该代码,就像这样编写:

StringBuilder sb = new StringBuilder("Ingredients: ");if (ingredients.length > 0) {sb.append(ingredients[0]);for (int i = 1; i < ingredients.length; i++) {sb.append(", ");sb.append(ingredients[i]);}
}return sb.toString();

这样,即使某些代码在过程中可能重复,也可以删除多余的if (i > 0) ,因为速度就是它的全部。

生活在边缘

空检查是一丁点的。 有时null对于我们的引用是有效值(例如,指示缺少值或错误),但是有时为了安全起见,我们添加了null检查。

其中某些检查可能永远不会失败(就此而言,null表示失败)。 一个经典的示例将包含一个断言,如下所示:

public static String l33tify(String phrase) {if (phrase == null) {throw new IllegalArgumentException("phrase must not be null");}return phrase.replace('e', '3');
}

如果您的代码运行良好,并且从未将null作为l33tify的参数l33tify ,则断言将永远不会失败。

在多次执行此代码而没有进入if语句的主体之后,JIT编译器可能会乐观地认为此检查很有可能是不必要的。 然后,它将继续编译该方法,将检查全部丢弃,就好像是这样写的:

public static String l33tify(String phrase) {return phrase.replace('e', '3');
}

这可以显着提高性能,这在大多数情况下可能是纯粹的胜利。

但是,如果那个幸福道路的假设最终被证明是错误的怎么办?

由于JVM现在正在执行本机已编译的代码,因此null引用不会导致模糊的NullPointerException ,而是导致实际的,苛刻的内存访问冲突。 JVM是它的底层生物,它将拦截产生的分段错误,进行恢复,并进行去优化后进行后续处理-编译器不能再假定null检查是多余的:它重新编译该方法,这次使用null检查。

虚拟精神错乱

JVM的JIT编译器与其他静态编译器(例如C ++编译器)之间的主要区别之一是,JIT编译器具有动态运行时数据,决策时可以依赖该动态运行时数据。

方法内联是一种常见的优化,其中编译器采用完整的方法并将其代码插入另一个代码中,以避免调用方法。 在处理虚拟方法调用(或动态调度 )时,这会有些棘手。

以以下代码为例:

public class Main {public static void perform(Song s) {s.sing();}
}public interface Song { void sing(); }public class GangnamStyle implements Song {@Overridepublic void sing() {System.out.println("Oppan gangnam style!");}
}public class Baby implements Song {@Overridepublic void sing() {System.out.println("And I was like baby, baby, baby, oh");}
}// More implementations here

该方法perform可能被执行数百万次,每一次方法的调用sing发生。 调用是昂贵的,尤其是诸如此类的调用,因为调用需要根据s的运行时类型每次动态选择要执行的实际代码。 在这一点上,内联似乎是一个遥不可及的梦想,不是吗?

不必要! 执行后, perform几千次,编译器可能会决定,根据其收集的统计数据,该调用的95%的目标的一个实例GangnamStyle 。 在这些情况下,HotSpot JIT可以执行乐观优化,以消除虚拟的sing调用。 换句话说,编译器将为这些代码生成本机代码:

public static void perform(Song s) {if (s fastnativeinstanceof GangnamStyle) {System.out.println("Oppan gangnam style!");} else {s.sing();}
}

由于此优化依赖于运行时信息,因此即使它是多态的,它也可以消除大多数sing调用。

JIT编译器还有很多技巧,但这些只是一些技巧,可让您了解当我们的代码由JVM执行和优化时的幕后故事。

我能提供帮助吗?

JIT编译器是面向简单人员的编译器; 它旨在优化简单的编写方式,并搜索日常标准代码中出现的模式。 帮助您的编译器的最佳方法是不要太努力地帮助它-只需像否则那样编写代码即可。

参考:来自Takipi博客的JCG合作伙伴 Niv Steingarten的JVM性能魔术技巧 。

翻译自: https://www.javacodegeeks.com/2013/06/jvm-performance-magic-tricks.html

jvm 性能

jvm 性能_JVM性能魔术相关推荐

  1. jvm原理及性能调优系列(jvm调优)

    jvm原理及性能调优系列(jvm调优) JVM设置: 1.设置合适的最大堆内存(新生代和老生代的最大和值)和最小堆内存(jvm启动时占用的操作系统内存大小),及设置好堆的比例分配. 2.设置合适的新生 ...

  2. #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)

    Linux + JVM + Mysql高级性能优化课程 课程名称:      Linux + JVM + Mysql高级性能优化 QQ群:      243242580(小白.菜鸟勿进)跟Java.M ...

  3. 【读书笔记】实战JAVA虚拟机JVM故障诊断与性能优化 读书笔记

    文章目录 1.概述 1.1 **第一章:初探java虚拟机** 1.2 认识java虚拟机的基本结构 1.3 常用Java虚拟机参数 1.4 垃圾回收器 1.5 垃圾收集器以及内存分配 1.6 性能监 ...

  4. 实战java虚拟机 百度云_《实战JAVA虚拟机 JVM故障诊断与性能优化》pdf百度云下载...

    内容简介· · · · · · 随着越来越多的第三方语言(Groovy.Scala.JRuby等)在Java虚拟机上运行,Java也俨然成为了一个充满活力的生态圈.<实战Java虚拟机--JVM ...

  5. Java面试题-JVM 和服务器性能评估

    1.JVM垃圾回收的时候如何确定垃圾?是否知道什么是GC Roots 垃圾指的是内存中不再使用的空间(主要指的就是堆内存),确定垃圾的方法有引用记数法和可达性分析法(但引用计数法存在对象之间循环引用的 ...

  6. <JVM下篇:性能监控与调优篇>03-JVM监控及诊断工具-GUI篇

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  7. JVM(四)_性能监控与调优

    不定期补充.修正.更新:欢迎大家讨论和指正 本文主要根据尚硅谷的视频学习,建议移步观看,其他参考资料会在使用时贴出链接 尚硅谷宋红康JVM全套教程(详解java虚拟机) 由于JVM的知识是互相穿插的, ...

  8. JVM(三).虚拟机性能监控故障处理工具

    JVM (三).虚拟机性能监控&故障处理工具 1.概述 系统定位问题,需要工具来导出出现问题的数据:这里的数据有异常堆栈,虚拟机日志,垃圾回收日志,线程快照,堆快照文件:工具就很多就是虚拟机自 ...

  9. e5620服务器性能如何,性能评估:处理器性能(1)

    六.性能评估 性能是服务器的一个重要指标,更强大的性能让服务器可以胜任更加繁重的工作,也能够实现更高的服务器整合率,为企业降低硬件上的成本.英特尔至强5600处理器相对至强5500在工艺.核心数量.缓 ...

最新文章

  1. 发现一个“佛系记账本”
  2. 怎样更新jar包中的某个class文件??
  3. 如何选择高性价比的控件产品
  4. 红帽集群套件RHCS四部曲(概念篇)
  5. 百度定位sdk使用说明
  6. cad lisp 背景遮罩_给文字批量添加边界偏移因子为1.1(或其他值)的背景遮罩的源程序(有详细注解)...
  7. 计算机操作系统安装实验报告,计算机操作系统实验报告.doc
  8. vue指令-循环指令
  9. tomcat 设置java_为tomcat配置java环境变量
  10. 软件测试的重要性与必要性,软件测试的目的和意义
  11. WPS如何隔列填充背景颜色
  12. 作业收集小程序推荐|视频作业收集、图片作业收集、文档作业收集
  13. 单细胞多组学联合应用
  14. python Flask之JinJa2
  15. 跨平台画图工具drawio使用指南——下载安装及常见功能指南
  16. 宝山区企业技术中心、区级工程技术研究中心给予奖励20万元
  17. SSH git初次克隆代码问题报错 fatal: unable to update url base from redirection:
  18. sqlite 汉字 排序
  19. 最新Ceph安装工具:Cephadm介绍与使用
  20. Lua脚本快速上手(附示例程序代码)

热门文章

  1. Java web文件下载断点续传
  2. 分布式Session共享解决方案
  3. 真正的问题应该在我身上……
  4. 充电提示音_iPhone如何自定义充电提示音,图文教程
  5. 19年8月 字母哥 第二章 RESTFul接口实现与测试 看到这里了
  6. windows为什么把linux打败了,快二十年了,人们为什么还是没有抛弃 Windows 转向 Linux?...
  7. 解决eclipse中tomcat无法识别maven web项目问题
  8. api restful_HATEOAS的RESTful服务。 记录超媒体API
  9. kafka mirror_SSL Kafka经纪人从Kafka Mirror Maker迁移到Brooklin的挑战
  10. neo4j 迁移_在Kubernetes中迁移Neo4j图模式