性能优化-AOT
5.19 AOT
AOT 指的是提前编译(Ahead-of-Time Compilation),直接将Java工程编译成可执行的二进制文件。相对于JIT在运行过程中逐步把热代码编译成二进制,他能较为明显的提高系统的启动速度和初始化运行速度,但目前看来,未必能比JIT方式更能提高系统性能。
在传统使用JIT情况下,JAVA系统通常启动较慢,且启动过程中涉及到类加载以及JIT执行,导致主机CPU一段时间内持续走高,响应较慢
除了能提高启动速度和运行性能外,使用AOT也带来其他好处
- 降低内存消耗
- 打包为较小的体积,适合资源收限制的环境,如移动应用
- 基于如上俩个优点,适合容器化,FAAS应用。
- 防止程序被破译修改。
Java目前最成熟的AOT工具是Graalvm,Oracle公司提供。如下是一个使用Graalvm编译运行Helllo World的过程
public static void main(String[] args){
System.out.println("hello word");
}使用native-image 编译,在我本机上运行约60秒,打包大小约8M
lijiazhi@lijiazhis-MacBook-Pro project % ls -l
total 13168
-rwxr-xr-x 1 lijiazhi staff 6732864 8月 20 12:44 helloworld
-rw-r--r-- 1 lijiazhi staff 434 8月 20 12:43 HelloWorld.class
-rw-r--r-- 1 lijiazhi staff 135 8月 20 12:43 HelloWorld.java可以通过Spring官方网站生成一个Graalvm+Spring Boot项目
@RestController
public class HelloWorld {
@ResponseBody
@RequestMapping("/")
public String say(){
return "hello,world";
}
}比较实用AOT和JIT的性能,可以看到AOT的性能无论是启动时刻,还是运行时刻性能都比较稳定。JIT启动时刻性能较低,这是因为存在加载class以及JIT需要运行过程再优化。但JIT在优化后的性能较AOT方式更好
| 比较项目 | Native | JIT |
|---|---|---|
| 启动速度 | 0.2 | 2.5 |
| 大小 | 80M | 20M+JVM(200M) |
| 打包耗时 | 300秒 | 8秒 |
| 启动时候性能 | 2400TPS | 1200TPS |
| 启动后性能 | 2400TPS | 4000TPS |
关于JIT,参考本书6.4 JIT
需要注意的是,企业级应用通常有很多懒加载,比如数据库连接池,Redis连接池,Dubbo注册等等,实际启动速度可能并没有比JVM运行更有优势。
另外,不是任何Java应用都能不经过调整,被GraalVM编译成二进制。 相对于类和资源被JVM动态加载执行,使用Graalvm 必须静态链接代码和资源,有较多的局限需要注意。比如
- 提供了编译参数,以指示动态资源,动态加载的类,以及需要的系统属性
- 反射和动态代理默认不支持,需要配置反射的类和方法。
- 不支持字节码生成技术,因此许多JVM高级特性无法使用。使用时候需要确认第三方包是否支持Native
因为,在业务系统使用Graalvm,还需要谨慎,确认应用自身以及依赖的框架和第三方包支持Natvie
,避免系统运行过程因为没有告知Graalvm编译,导致运行中出错。
