资讯详情

java 堆栈_低延迟Java应用的秘密 -- JVM(Java 虚拟机)预热调优

3e5a9bb06306b1949ad84ce4fff1f829.png
此文是作者英文原文的翻译文章,英文原文在: http:// todzhang.com/posts/2018 -06-10-jvm-warm-up/

JVM预热

低延迟Java在某些应用场景下,虚拟机的应用对系统至关重要。例如,在某些应用场景中外汇交易系统等待金融业的核心体系。本文探讨了如何使用它。Java虚拟机预热提高系统效率。

优化几调整JVM每个过程都被称为预热 请记住,对于低延迟应用程序,我们需要提前先缓存所有类别-以便在运行过程中立即访问它们。

逃逸分析

逃逸分析是Java Hotspot Server编译器可用于分析新对象的使用范围,并决定是否Java堆上分配它的技术。 对象的转义状态可能如下:

  • GlobalEscape –对象转义法和线程。例如,对象存储在静态字段中,或存储在转义对象字段中,或作为当前方法的结果返回。
  • ArgEscape –作为参数传通过分析被调用方法的字节码来确定的。
  • NoEscape –标量可替换对象,即可从生成的代码中删除其分配。

经过逃逸分析,服务器编译器从生成的代码中消除了标量可替换对象的分配和相关。服务器编译器还消除了所有非全球转换对象的锁。它不会用非全球转换对象的堆栈分配来替换堆分配。

JIT积极的内联方法消除了方法调用的费用。可内联的方法包括静态、私有或最终的方法,但如果可以确定它们没有被覆盖,也可以包括公共方法。因此,以前生成的代码可能无效。因为在每个地方内联每种方法都需要时间,生成不合理的大二进制文件,所以JIT在达到阈值之前,编译器首先到达到阈值。确定哪些方法很受欢迎,JVM计数器将被保留多少次,检查方法已被调用多少次,循环迭代已执行多少次。这意味着内联网只发生在稳定状态之后,所以你需要重复一定数量的操作,然后有足够的总结分析信息JIT编译器执行其工作。

你可以试着打开它Java命令行标志窥视正在发生的事情,而不是试图猜测JIT在做什么:-XX: PrintCompilation -XX: UnlockDiagnosticVMOptions -XX: PrintInlining 这是他们的工作:

   -XX:  PrintCompilation:JIT记录发生时的编译    -XX:  UnlockDiagnosticVMOptions:使用其它标志,例如-XX:  PrintInlining 

GlobalEscape和ArgEscape对象必须在堆上分配,但对于ArgEscape一些锁定和内存同步费用可以删除,因为这些对象只能在调用线程中看到。

NoEscape对象可以自由分配,比如堆栈而不是堆栈。事实上,在某些情况下,甚至不需要构建一个对象,而只构建对象的标量值,如对象Integer的int。同步也可能被删除,因为我们知道只有这个线程才能使用对象。例如,如果我们使用一些古老的东西StringBuffer(与StringBuilder相反,它有同步方法),这些同步可以安全删除。

EA当前仅在C2 HotSpot因此,我们必须确保编译器是可用的-server模式运行。

为什么重要

理论上可以用EA将NoEscape对象分配在堆栈上,甚至可以分配给CPU寄存器可以很快执行。

当我们在堆上分配对象时,我们开始消耗CPU缓存,因为对象被放置在堆放的不同地址上,它们之间可能会有很长的距离。这样,我们就会很快耗尽L1 CPU缓存,并且性能会下降。另一方面,通过EA我们正在使用堆栈分配(很可能)L1高速缓存中的内存。因此,EA与堆栈分配将改善我们的数据本地化。从性能的角度来看,这很好。

显然,当我们使用带有堆栈分布的堆栈时EA垃圾收集的运行频率要低得多。这可能是最大的性能优势。回想起来,每次JVM当我们运行一个完整的堆扫描时,我们都会从我们的CPU中获取性能,并且CPU高速缓存将很快耗尽。更不用说我们是否在服务器上调出虚拟内存了GC破坏性能。

EA最重要的优点不是性能。 EA允许我们使用Lambda,函数、流量、迭代器等局部抽象,不会造成任何明显的性能损失,使我们能够编写更好、更容易读取的代码。描述我们在做什么,而不是如何完成它。

GC清理堆,而不是堆栈。方法返回调用方时,堆栈会自动清理,将堆栈指针重置为以前的值。GC将在执行EA / C在编译之前,清理堆栈中最终的对象。实际例子(或更确切地说,它们的相应表达形式)位于堆栈上EA在优化的上下文中,堆栈上没有引用对象。

JIT优化

一些JIT编译技术

内联是Java HotSpot VM最常用的JIT编译技术之一,它是将方法的主体替换为调用该方法的位置的实践。内联节省了调用方法的成本;无需创建新的堆栈框架。默认情况下,Java HotSpot VM内联包含少于35个字节JVM字节码的方法。

Java HotSpot VM另一种常见的优化是单态调度,这取决于观察到的事实,即在大多数情况下,没有办法导致对象引用属于一种类型,而在另一种类型中有另一种路径。

你可能会想Java静态类型将排除通过不同代码路径有不同类型的情况,但请记住,子类型的实例始终是超级类型的有效实例(在Barbara Liskov之后,这个原理叫Liskov替换原理)。这种情况意味着方法可能有两条路径(例如,一条路径传递一个超级类型的例子,一条路径传递一个子类型的例子)Java静态类型的定义是合法的(而且确实会在实践中)。

但在正常情况下(单态情况),不会有不同类型的依赖路径。因此,我们知道调用的确切方法是在传输对象上调用方法时定义的,因为我们不需要检查实际使用的替代品。这意味着我们可以消除虚拟方法搜索的费用,因此JIT编译器可以发送优化的机器代码,通常比等效C 调用要快(因为在C 情况下,无法轻松消除虚拟查找)。

两种Java HotSpot VM不同的编译模式使用不同的编译模式JIT编译技术,对于相同的Java它们可以输出非常不同的机器代码。然而,现代Java两种编译模式可以同时使用。

Java HotSpot VM优化许多其他技术JIT编译生成的代码。循环优化、类型锐化、死代码消除和内部函数Java HotSpot VM尝试尽可能多地优化代码的其他方法。技术通常一层一层地放在另一层上,所以一旦应用了优化,编译器可能会看到更多可执行的优化。

编译模式

在Java HotSpot VM实际上有两个单独的内部JIT编译模式分别称为编译模式C1和C2。 C1用于需要快速启动和坚如磐石的优化; GUI该编译器的理想选择通常是应用程序。另一方面,C(主要是服务器端)应用程序最初用于长期运行。在某些Java SE 在7个更高版本之前,分别使用-client和-server这两种模式可用于开关

两种编译模式使用不同的技术JIT编译,同样的Java它们可以输出非常不同的机器代码。但是,现代Java两种编译模式可以同时使用。从某些事实来看,为了利用这一事实Java SE 从更高的版本开始,提供了一个叫做分层编译的新功能。此功能在开始时使用C为了提供更好的启动性能,编译适当预热应用程序,C编译模式将接管其工作,以提供更具攻击性的优化,并通常提供更好的性能。随着Java SE 随着8的到来,分层编译已成为默认行为。

Java内存监控工具

pemi$ jps | grep Main 50903 Main pemi$ jmap -histo 50903 | head  num     #instances         #bytes  class name  ----------------------------------------------    1:            95       42952184  [I    2:          1079         101120  [C    3:           485          55272  java.lang.Class    4:           526          25936  [Ljava.lang.Object;    5:            13          25664  [B    6:          1057          25368  java.lang.String    7:            74           5328  java.lang.reflect.Field 

jmap-内存映射

工具或选项的说明和用法 Java任务控制

Java Mission Control(JMC)

是用于HotSpot JVM的新JDK分析诊断工具平台。它是一种基本监控、管理和生产时间分析和诊断的高性能工具套件。 Java Mission Control性能分析费用最小化,性能费用通常是性能分析工具遇到的问题。Java Mission Control。

jcmd实用程序

jcmd将诊断命令请求发送到实用程序中JVM,控制这些要求Java Flight Records很有用。 JFR用于飞行记录事件JVMJava应用程序进行故障排除和诊断。请参见jcmd实用程序。

Java VisualVM

该实用程序提供了一个可视界面,用于在Java应用程序在Java虚拟机上运行时查看有关Java应用程序的详细信息。此信息可用于对本地和远程应用程序进行故障排除,以及对本地应用程序进行性能分析。请参阅Java VisualVM。 JConsole实用程序

该实用程序是基于Java管理扩展(JMX)的监视工具。该工具使用Java虚拟机中的内置JMX工具来提供有关正在运行的应用程序的性能和资源消耗的信息。请参见JConsole。 jmap实用程序

该实用程序可以从Java进程,核心文件或远程调试服务器获取内存映射信息,包括堆直方图。请参阅jmap实用程序。 jps实用程序

该实用程序列出了目标系统上已检测到的Java HotSpot VM。该实用程序在嵌入式VM的环境中非常有用,也就是说,它是使用JNI Invocation API而不是Java启动器启动的。请参阅jps实用程序。 jstack实用程序

该实用程序可以从Java进程获取Java和本机堆栈信息。在Oracle Solaris和Linux操作系统上,该实用程序可以从核心文件或远程调试服务器中获取信息。请参阅jstack实用程序。 jstat实用程序

该实用程序使用Java中的内置工具来提供有关正在运行的应用程序的性能和资源消耗的信息。诊断性能问题(尤其是与堆大小和垃圾回收相关的问题)时可以使用该工具。请参见jstat实用程序。 jstatd守护程序

该工具是一个远程方法调用(RMI)服务器应用程序,它监视已检测Java虚拟机的创建和终止,并提供一个接口,以允许远程监视工具连接到在本地主机上运行的VM。请参见jstatd守护程序。 visualgc实用程序

该实用程序提供了垃圾收集系统的图形视图。与jstat一样,它使用Java HotSpot VM的内置工具。请参阅visualgc工具。 本机工具

$ jps
16217 MyApplication
16342 jps

The utility lists the virtual machines for which the user has access rights. This is determined by access-control mechanisms specific to the operating system. On Oracle Solaris operating system, for example, if a non-root user executes the jps utility, then the output is a list of the virtual machines that were started with that user's uid.

In addition to listing the PID, the utility provides options to output the arguments passed to the application's main method, the complete list of VM arguments, and the full package name of the application's main class. The jps utility can also list processes on a remote system if the remote system is running the jstatd daemon.

无GC的Java

没有GC的Java开发 Coral Blocks开发的所有产品都具有非常重要的功能,可以将零垃圾抛在后面。由于Java垃圾收集器(即GC)施加的延迟对于高性能系统是不可接受的,并且由于无法关闭GC,因此Java实时系统的最佳选择是根本不产生任何垃圾。想象一下,GC永远不会启动。想象一下一个高性能匹配引擎,其运行时间为微秒级,每秒发送和接收数十万条消息。如果GC在任何给定时间决定以1毫秒以上的延迟开始运行,则系统中的中断将是巨大的。因此,如果要使用Java开发具有最小方差和延迟的实时系统,最好的选择是正确执行此操作,而不会为GC创建任何垃圾。

热身,检查GC和采样

确保您的系统不产生任何垃圾的关键是从开始到完成数百万次预热您的关键路径,然后再检查数百万次内存分配。如果它随着迭代次数的增加而线性地分配内存,则很可能会产生垃圾,您应该使用堆栈跟踪

--end--

标签: 8pemi连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台