JIT编译优化点-方法内联

JIT

java程序猿-你的代码居然慢在JIT方法内联上

通常JIT的有以下几种手段来优化JVM的性能:

1、针对特定CPU型号的编译优化,JVM会利用不同CPU支持的SIMD指令集来编译热点代码,提升性能。像intel支持的SSE2指令集在特定情况下可以提升近40倍的性能。

2、减少查表次数。比如调用Object.equals()方法,如果运行时发现一直是String对象的equals,编译后的代码可以直接调用String.equals方法,跳过查找该调用哪个方法的步骤。

3、逃逸分析。JAVA变量默认是分配在主存的堆上,但是如果方法中的变量未逃出使用的生命周期,不会被外部方法或者线程引用,可以考虑在栈上分配内存,减少GC压力。另外逃逸分析可以实现锁优化等提升性能方法。

4、寄存器分配,部分变量可以分配在寄存器中,相对于主存读取,更大的提升读取性能。

5、针对热点代码编译好的机器码进行缓存。代码缓存具有固定的大小,并且一旦它被填满,JVM 则不能再编译更多的代码。

6、方法内联,也是JIT实现的非常有用的优化能力,同时是开发者能够简单参与JIT性能调优的地方。

 

 

 

 

要搞清楚为什么方法内联有用,首先要知道当一个函数被调用的时候发生了什么

1、首先会有个执行栈,存储目前所有活跃的方法,以及它们的本地变量和参数

2、当一个新的方法被调用了,一个新的栈帧会被加到栈顶,分配的本地变量和参数会存储在这个栈帧

3、跳到目标方法代码执行

4、方法返回的时候,本地方法和参数会被销毁,栈顶被移除

5、返回原来地址执行

 

 

方法内联的原理

方法内联就是把被调用方函数代码”复制”到调用方函数中,来减少因函数调用开销的技术。

我们写一个简单的两数相加程序,被内联前的代码:

    private int add4(int x1, int x2, int x3, int x4) { 
        return add2(x1, x2) + add2(x3, x4); 
    } 

private int add2(int x1, int x2) { 
        return x1 + x2; 
    } 

运行一段时间后JVM会把add2方法去掉,并把你的代码翻译成:

    private int add4(int x1, int x2, int x3, int x4) { 
        return x1 + x2 + x3 + x4; 
    }

 

方法内联的条件

JVM会自动的识别热点方法,并对它们使用方法内联优化。那么一段代码需要执行多少次才会触发JIT优化呢?通常这个值由-XX:CompileThreshold参数进行设置:

使用client编译器时,默认为1500;

使用server编译器时,默认为10000;

但是一个方法就算被JVM标注成为热点方法,JVM仍然不一定会对它做方法内联优化。其中有个比较常见的原因就是这个方法体太大了,分为两种情况。

如果方法是经常执行的,默认情况下,方法大小小于325字节的都会进行内联(可以通过** -XX:MaxFreqInlineSize=N**来设置这个大小)

如果方法不是经常执行的,默认情况下,方法大小小于35字节才会进行内联(可以通过** -XX:MaxInlineSize=N **来设置这个大小)

我们可以通过增加这个大小,以便更多的方法可以进行内联;但是除非能够显著提升性能,否则不推荐修改这个参数。因为更大的方法体会导致代码内存占用更多,更少的热点方法会被缓存,最终的效果不一定好。

如果想要知道方法被内联的情况,可以使用下面的JVM参数来配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值