jvm 性能_JVM性能魔术

jvm 性能

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

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 性能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java高级编程期末考试题_java高级编程考题

Java高级课程测试1在进行swing开发时&#xff0c;经常用的布局管理器有那几种&#xff1f;(5)2Gui组件&#xff0c;容器&#xff0c;框架&#xff0c;到底有怎样的关系&#xff0c;请举例说明&#xff1f;(5)3在进行swing开发中会用到事件处理&#xff0c;那事件处理的三个主要…

spring 事务 会话_测试Spring的“会话”范围

spring 事务 会话在基于Spring的Web应用程序中&#xff0c;bean的作用域可以是用户“会话”。 从本质上讲&#xff0c;这意味着对会话范围Bean的状态更改仅在用户会话范围内可见。 本条目的目的是简单地突出显示Spring Test MVC提供的一种方法&#xff0c;用于测试将会话范围的…

Hollowjars,部署扫描程序以及Wildfly群体为何很棒

在上一篇文章中&#xff0c;我描述了如何使用OpenLiberty和maven作为独立服务器或maven构建的一部分来启动服务器&#xff0c;以及如何创建fatjar包。 在这篇文章中&#xff0c;我正在研究如何使用Wildfly群。 我仍在尝试使MicroProfile在Wildfly full上运行&#xff0c;因此&…

Java调用跟踪系统_Tracer:在分布式系统中的调用跟踪和日志相关

Tracer: Distributed system tracingTracer noun, /ˈtɹeɪsɚ/: A round of ammunition that contains a flammable substance that produces a visible trail when fired in the dark.Tracer is a library that manages custom trace identifiers and carries them through …

java 垃圾回收手动回收_Java垃圾回收(3)

java 垃圾回收手动回收接下来是我的前两篇垃圾收集博客文章&#xff1a; GC热点概述 。 并行垃圾收集器 。 并发标记扫描 Hotspot中的并行垃圾收集器旨在最大程度地减少应用程序进行垃圾收集所花费的时间&#xff0c;这称为吞吐量 。 对于所有应用程序而言&#xff0c;这并不…

java测试netty_《Netty官方文档》基准测试

原文链接 译者&#xff1a;lijunshuNetty有一个模块叫’netty-microbench’&#xff0c;我们可以用他来执行一系列的微型基准测试。Netty-microbench是基于OpenJDK JMH构件的(HotSpot的推荐基准测试方案)。当你开始netty基准测试时&#xff0c;你不需要额外的依赖。运行基准测…

Java命令行界面(第30部分):观察

这个有关Java命令行参数解析的系列文章由四个月来发表的29篇文章组成&#xff0c;涵盖了28个不同的开放源代码库&#xff0c;可用于解析Java命令行参数。 这篇文章收集了可以从本系列的前29篇文章中得出的一些观点&#xff0c;并提供了一些一般性的考虑&#xff0c;以便在选择2…

java导出excel 科学计数法_基于Java将Excel科学计数法解析成数字

需要注意的是一般的科学表达式是1.8E12 1.8E-12而在Excel中的科学表达式是1.8E12 1.8E-12我写的科学计数法的正则表达式是(-?\d\.?\d*)[Ee]{1}[\-]?[0-9]*导入EXCEL数据时将科学计数法解析成数字&#xff0c;Java代码&#xff1a;import java.text.DecimalFormat;import jav…

java描边_shape描边设置是否显示四周描边

android:width"1pt"/>android:topRightRadius"30pt"android:bottomRightRadius"30pt" />效果图如下&#xff1a;这里设置了左边描边不显示设置虚线&#xff1a;android:shape"line">android:dashGap"3pt"android:d…

java 垃圾回收手动回收_Java垃圾回收(2)

java 垃圾回收手动回收并行清理 今天&#xff0c;我们介绍了并行GC的工作原理。 具体来说&#xff0c;这是在Eden上运行并行Scavenge收集器&#xff0c;在Tenured一代上运行Parallel Mark and Sweep收集器的组合。 您可以通过传递-XX&#xff1a; UseParallelOldGC来获得此选项…

java正则表达式性能_译:Java 中的正则表达式性能概述

译者&#xff1a;Darren Luo1. 概述在本快速教程中&#xff0c;我们将展示模式匹配引擎是如何工作的。我们还将介绍在 Java 中优化正则表达式的不同方式。有关正则表达式的的使用介绍&#xff0c;请参阅此文。2. 模式匹配引擎java.util.regex 包使用了一种叫做 Nondeterministi…

带注释的控制器– Spring Web / Webflux和测试

Spring Webflux和Spring Web是两个完全不同的Web堆栈。 但是&#xff0c; Spring Webflux继续支持基于注释的编程模型 使用这两个堆栈定义的端点可能看起来相似&#xff0c;但是测试该端点的方式却大不相同&#xff0c;并且编写此端点的用户必须知道哪个堆栈处于活动状态并相应…

jquery解析java对象数组_Javascript / jQuery初学者:将对象推送到数组

Well you are changing the reference of same object通过示例了解它是如何工作的let a {};let b a;a.name xyz;a.name abc;console.log(a.name)console.log(b.name)所以在上面的示例中我们有两个变量a和b . a是一个对象 .每当我们更新名称时&#xff0c;最后一个值将被新的…

java查看jvm对象个数_jmap-查看 jvm 内存对象信息

jmap 概述命令jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件&#xff0c;也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。参数option&#xff1a;选项参数。pid&#xff1a;需要打印配置信息的进程ID。executable&#xff1a;产…

OpenHub框架进行的异步通信

在本系列的前一部分中&#xff0c;我们介绍了OpenHub框架 。 这部分显示了框架最强大的功能之一- 异步消息传递模型 。 当源系统无法等待目标系统的响应时&#xff0c;将使用系统之间的异步通信。 有以下几个原因&#xff1a; 源系统必须尽可能地响应 &#xff0c;并且不受外…

Java实现C语言select函数_一道面试题目,分别用sql 和java,c++, c语言实现,

引用来自“雨翔河”的评论获取国家假日办的的信息&#xff0c;然后根据假日办提供的信息来搞定。日期的话&#xff0c;哈哈&#xff0c;找个提供日期查询的接口&#xff0c;借用一下来查日期&#xff0c;也搞定了。总之哪里有的抄就抄哪里的。再来一个笨蛋的意见&#xff0c;把…

java注解的反射_Java注解与反射

概要本文主要是总结Java注解与反射的相关知识&#xff0c;加深自己对Java类动态语言的理解&#xff0c;同时为日后学习Spring打下基础。注解&#xff1a;什么是注解Annotation的作用不是程序本身&#xff0c;但是可以对程序作出解释。可以被其他程序(比如&#xff1a;编译器等)…

工厂设计模式和策略设计模式_设计模式:策略

工厂设计模式和策略设计模式这次我想谈谈策略设计模式 。 通过这种方式&#xff0c;我开始撰写有关行为设计模式的文章。 这种模式表示对象之间的某些交互模式&#xff0c;以使代码更灵活且组织得更好。此方法的最本质点是对象之间的松散耦合。 当您的应用程序中有多个实现目的…

java 8 排序反转_Java 8 排序小结

1、概述首先&#xff0c;让我们先定义一个简单的实体类&#xff1a;Datapublic class Human {private String name;private int age;public Human() {super();}public Human(final String name, final int age) {super();this.name name;this.age age;}}2、不使用Lambda表达式…

如何将不带web.xml的Spring应用程序部署到Tomcat

介绍 由于Servlet 3规范不再需要web.xml来配置Web应用程序&#xff0c;因此已通过使用注释代替。 在本文中&#xff0c;我们将研究如何在不使用web.xml情况下将简单的基于Spring的应用程序部署到Tomcat 8.5。*。 创建一个空的应用程序 使用以下命令使用maven webapp原型创建一…