Java高级——Graal编译器介绍
创始人
2024-03-29 07:47:51

Graal编译器介绍

Graal编译器由Java实现,支持提前编译和即时编译

JDK9推出Java虚拟机编译器接口(Java-Level JVM CompilerInterface,JVMCI),将Graal从HotSpot代码中独立出来(即可外部挂载)

构建编译调试环境

这里大坑,试了很多个版本都报错,文件放置在自己的Home下,不要放在奇奇怪怪的目录,保持同一个用户,否则可能会有权限问题!!!

下载构建工具mx

git clone https://github.com/graalvm/mx.git
git checkout 5.247.4

下载Graal编译器代码

git clone https://github.com/oracle/graal.git
git checkout release/graal-vm/19.3

使用带JVMCI的JDK 1.8,可在如下网站下载

https://github.com/graalvm/openjdk8-jvmci-builder/releases

Python版本如下

在这里插入图片描述

配置编译环境,将mx添加到环境变量,指定编译使用的JDK

export PATH=$PATH:/home/song/mx
export JAVA_HOME=/home/song/Downloads/jdk1.8

编译,无报错即编译成功

cd graal/compiler
mx build

编译完成后构建为Eclipse项目

cd graal/compiler
mx eclipseinit

下载Eclipse安装,修改eclipse.ini设置最大堆为2G

在这里插入图片描述

启动Eclipse,将编译graal的JDK设置为默认,Window-Java-installed JREs,删除原来的,点击add-Standard VM-Diectory选择存放目录会自动识别

在这里插入图片描述

在installed JREs下面的Execution Enviroments选择对应JDK并打勾

在这里插入图片描述

在Java-Compiler选择对应JDK

在这里插入图片描述

File-Import-General-Existing Projects into Workspace选择graal根目录导入项目

在这里插入图片描述

项目有报错但不影响下面步骤

JVMCI编译器接口

JVMCICompiler接口如下,除了接收字节码之外,还有方法的局部变量槽个数、操作数栈深度等信息

interface JVMCICompiler {void compileMethod(CompilationRequest request);
}interface CompilationRequest {JavaMethod getMethod();
}interface JavaMethod {byte[] getCode();int getMaxLocals();int getMaxStackSize();ProfilingInfo getProfilingInfo();... // 省略其他方法
}

通过继承关系,可看到HotSpotGraalCompiler实现了JVMCI

在这里插入图片描述

对于如下程序

public class Demo {public static void main(String[] args) {while (true) {workload(14, 2);}}private static int workload(int a, int b) {return a + b;}
}

先使用分层编译,添加虚拟机参数

-XX:+PrintCompilation -XX:CompileOnly=Demo::workload

可看到wordload()方法被分层编译了多次,“made not entrant”的输出就表示了方法的某个已编译版本被丢弃过

在这里插入图片描述

若只使用graal编译器运行,添加如下参数

-Djvmci.class.path.append=/home/song/graal/compiler/mxbuild/dists/jdk1.8/graal.jar:/home/song/graal/sdk/mxbuild/dists/jdk1.8/graal-sdk.jar
-XX:+UnlockExperimentalVMOptions
-XX:+EnableJVMCI
-XX:+UseJVMCICompiler
-XX:-TieredCompilation
-XX:+PrintCompilation
-XX:CompileOnly=Demo::workload

为了验证结果,修改HotSpotGraalCompiler类的compileMethod()方法,输出编译的方法名称和编译耗时

public CompilationRequestResult compileMethod(CompilationRequest request) {long time = System.currentTimeMillis();CompilationRequestResult result = compileMethod(request, true, graalRuntime.getOptions());System.out.println("compile method:" + request.getMethod().getName());System.out.println("time used:" + (System.currentTimeMillis() - time));return result;
}

运行代码,可看到对应输出

在这里插入图片描述

代码中间表示

Graal采用理想图作为中间表示,其是有向图,节点表示程序的元素,边表示数据或控制流,对如下程序

public class Demo {public static void main(String[] args) {while (true) {workload(14, 2);}}static int workload(int a, int b) {return (a + b) * (a + b);}
}

添加参数-Dgraal.Dump输出理想图

-Djvmci.class.path.append=/home/song/graal/compiler/mxbuild/dists/jdk1.8/graal.jar:/home/song/graal/sdk/mxbuild/dists/jdk1.8/graal-sdk.jar
-XX:+UnlockExperimentalVMOptions
-XX:+EnableJVMCI
-XX:+UseJVMCICompiler
-XX:-TieredCompilation
-XX:+PrintCompilation
-XX:CompileOnly=Demo::workload
-Dgraal.Dump

可看到类似输出

在这里插入图片描述

在如下地址下载Ideal Graph Visualizer

https://www.oracle.com/technetwork/graalvm/downloads/index.html

修改idealgraphvisualizer/etc/idealgraphvisualizer.conf配置JDK

在这里插入图片描述

通过./idealgraphvisualizer/bin/idealgraphvisualizer打开软件,打开上面生成的文件

在这里插入图片描述
如上,参数的加法操作只进行了一次,然后流出两条数据流到乘法操作的输入中,说明产生了公共子表达式消除,而对于如下程序

public class Demo {private static int A;private static int B;public static void main(String[] args) {while (true) {workload();}}static int workload() {return (getA() + getB()) * (getA() + getB());}public static int getA() {return A;}public static int getB() {return B;}}

getA()和getB()方法内部逻辑不确定的,只能在内联之后才能考虑进一步的优化措施,函数调用时无法实现公共子表达式消除,如下进行了4次调用方法、2次加法、1次乘法

在这里插入图片描述

代码优化

生成理想图的函数为greateGraph(),其数据结构为ValueNode子类节点集合,转换到理想图过程被封装在BytecodeParser类,

以BytecodeParser::genArithmeticOp()中的iadd操作为例,先出栈2个操作数,通过genIntegerAdd()相加再入栈

在这里插入图片描述

过程由AddNode节点表示,代码如下

protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) {return AddNode.create(x, y, NodeView.DEFAULT);
}

如下,AddNode在创建节点时调用canonical(),在其中优化缩减理想图(即代码优化),如进行了

  • 算术聚合(如将(a+1)+2聚合为a+3)
  • 符号合并(如将(a-b)+b合并为a)等操作
public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {BinaryOp op = ArithmeticOpTable.forStamp(x.stamp(view)).getAdd();Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view));ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view);if (tryConstantFold != null) {return tryConstantFold;}if (x.isConstant() && !y.isConstant()) {return canonical(null, op, y, x, view);} else {return canonical(null, op, x, y, view);}
}

而公众子表达式消除实现在tryGlobalValueNumbering()方法中,若发现了可以进行消除的算术子表达式,则找出重复的节点替换、删除,如下

public boolean tryGlobalValueNumbering(Node node, NodeClass nodeClass) {if (nodeClass.valueNumberable()) {Node newNode = node.graph().findDuplicate(node);if (newNode != null) {assert !(node instanceof FixedNode || newNode instanceof FixedNode);node.replaceAtUsagesAndDelete(newNode);COUNTER_GLOBAL_VALUE_NUMBERING_HITS.increment(debug);debug.log("GVN applied and new node is %1s", newNode);return true;}}return false;
}

机器码生成

先生成低级中间表示(LIR,与具体机器指令集相关的中间表示),再由HotSpot产生机器码,对如下程序

public class Demo {public static void main(String[] args) {while (true) {workload(14, 2);}}static int workload(int a, int b) {return a+b;}
}

添加虚拟机参数

-Djvmci.class.path.append=/home/song/graal/compiler/mxbuild/dists/jdk1.8/graal.jar:/home/song/graal/sdk/mxbuild/dists/jdk1.8/graal-sdk.jar
-XX:+UnlockExperimentalVMOptions
-XX:+EnableJVMCI
-XX:+UseJVMCICompiler
-XX:-TieredCompilation
-XX:+PrintAssembly
-XX:CompileOnly=Demo::workload
-XX:+DebugNonSafepoints

从下面地址下载hsdis-amd64.so放到$JAVA_HOME/lib/amd64

https://github.com/cmuramoto/hsdis

编译生成汇编如下

在这里插入图片描述

加法操作在AddNode::generate()中调用ArithmeticLIRGeneratorTool的emitAdd()方法生成机器码,将其改为emitSub

在这里插入图片描述

可看到对应汇编变成了sub

在这里插入图片描述

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...