1.CPU相关代码
1.1.Advanced Vector Extensions
1.1.1.AVX
1.1.2.2013年,Intel为Haswell以及之后的芯片引入了AVX2
1.1.3.2016年,Intel又引入了AVX-512指令
1.1.4.JDK 8不支持这些指令
1.1.5.JDK 11支持
1.2.-XX:UseAVX=N
1.2.1.0
1.2.1.1.不使用AVX指令
1.2.2.1
1.2.2.1.使用Intel AVX 1指令(对于Sandy Bridge和之后的处理器)
1.2.3.2
1.2.3.1.使用Intel AVX 2指令(对于Haswell和之后的处理器)
1.2.4.3
1.2.4.1.使用Intel AVX-512指令(对于Knights Landing和之后的处理器)
1.3.-XX:UseSSE=N
1.3.1.支持Intel流SIMD扩展1到4
1.3.1.1.Streaming SIMD Extensions,SSE
1.3.2.针对奔腾系列处理器的
2.分层编译的权衡
2.1.当在内存受限的环境中运行时有理由关闭它
2.2.给定足够长的预热期,禁用分层编译时的执行情况和开启时应该是差不多的
2.3.javac编译器
2.3.1.包含额外调试信息的-g标志不会影响性能
2.3.2.在Java应用程序中使用final关键字并不能更快地编译代码
2.3.3.用较新的javac版本重新编译通常不会使应用程序更快
2.3.3.1.JDK 11引入了一种新的字符串连接方式,可以比以前的版本更快,但需要重新编译代码才能用
3.GraalVM
3.1.一个新的虚拟机
3.1.1.可以运行许多其他语言的代码
3.2.两个版本
3.2.1.完全开源的社区版(Community Edition,CE)
3.2.1.1.社区版比企业版慢
3.2.2.商用的企业版(Enterprise Edition,EE)
3.3.对JVM性能有两个重要贡献
3.3.1.插件技术允许GraalVM生成完全原生的二进制文件
3.3.2.以常规JVM的模式运行,只是它包含了一个新的C2编译器实现
3.3.2.1.这个编译器是用Java写的
3.3.2.2.传统的C2编译器是用C++写的
3.4.-XX:+UnlockExperimentalVMOptions
3.4.1.默认值是false
3.5.-XX:+EnableJVMCI
3.5.1.默认值是false
3.6.-XX:+UseJVMCICompiler
3.6.1.默认值是false
4.提前编译
4.1.ahead-of-time compilation,简称AOT compilation
4.2.最初仅在JDK 9的Linux版本中可用
4.2.1.JDK 11时所有平台都可以用了
4.3.启动速度更快
4.3.1.目前,应用程序类数据共享给启动性能带来的提升更大,而且它已经是平台完全支持的特性
4.3.2.提前编译针对的是像REST服务器这样启动时间相对比较长的程序
4.3.2.1.加载共享库的时间就被较长的启动时间抵消了,提前编译就更有优势
4.4.jaotc工具
4.4.1.生成一个共享库,其中包含你选出的编译过的类
4.4.2.然后通过运行参数将共享库加载到JVM中
$ java -XX:+UnlockDiagnosticVMOptions -XX:+LogTouchedMethods \
-XX:+PrintTouchedMethodsAtExit <other arguments>
java/net/URI.getHost:()Ljava/lang/String;
4.4.5.为了生成methods.txt文件,需要保存这些输出内容,然后在每一行前添加compileOnly命令并删除方法参数之前的冒号
$ jaotc --compile-commands=/tmp/methods.txt \
--output JavaBaseFilteredMethods.so \
--compile-for-tiered \
--module java.base
4.4.7./tmp/methods.txt文件中
compileOnly java.net.URI.getHost()Ljava/lang/String;
4.5.如果不让预编译的方法被C2编译器编译,那么服务器预热后的性能就会比它最终可能达到的性能差
4.6.-XX:+PrintAOT
4.6.1.在预编译方法被JVM使用时会产生输出
4.6.2.默认值是false
4.7.对于比较大的程序有好处
4.8.对于很小的、快速运行的程序没有帮助,甚至会阻碍它们的运行
5.GraalVM原生编译
5.1.生成不需要JVM的可执行文件
5.1.1.是短期程序的理想选择
5.2.生成的二进制文件启动速度很快,特别是相较于在JVM中运行的程序
5.3.GraalVM优化代码时并没有C2编译器那么激进,所以对于运行得足够久的应用程序,传统的JVM最终会胜出
5.4.GraalVM原生二进制文件在执行期间不会使用C2编译器编译类
5.5.原生程序的内存占用在开始时比传统JVM少得多
5.5.1.随着程序的运行和堆的增长,这种内存优势会逐渐消失