inline 方法内联

inline 方法内联

什么是方法内联?

  • 如果你是C/C++ 程序员,你可能十分了解,C/C++ 使用inline关键字,它用作编译器指令,建议(但不要求)编译器通过执行内联扩展(即在每个函数调用的地址处插入函数代码)来内联替换函数的主体,从而节省函数调用的开销。
  • 如果你是Java 码农,你在背八股时可能听过,JVM在进行JIT优化时会使用到方法内联进行优化
  • 如果你是goer,在看go sdk 时会看到//go:noinline,提示编译器不要进行方法内联

所以方法内联到底是什么呢?

方法内联就是:将函数调用调用处替换为被调用函数主体的一种编译器优化手段

举个例子:

C 复制代码
void func(){
    // doSomeThing...
}

int main(){
    while(true){
        func(); // 函数调用,涉及额外的开销
    }
}

//---After inline

int main(){
    while(true){
        // doSomeThing... // 函数体直接复制到这里,减少了函数调用的开销
    }
}

JIT 方法内联

作为Java程序员我们是决定不了哪个方法需要内联的,但是我们可以看到JIT对方法进行了内联操作

打开JVM 参数:

ruby 复制代码
-XX:+PrintCompilation             //记录 JIT 编译发生的时间
-XX:+UnlockDiagnosticVMOptions    //启用其他标志
-XX:+PrintInlining                //打印要内联的方法

运行示例代码如下:

Java 复制代码
package org.example.inline;

public class Main {
    private static class Sum {
        private final int n;

        public Sum(int n) {
            this.n = n;
        }

        public long getTotalSum() {
            long totalSum = 0;
            for (int i = 0; i < n; i++) {
                totalSum += i;
            }
            return totalSum;
        }
    }

    private static long calculateSum(int n) {
        return new Sum(n).getTotalSum();
    }

    private static final long NUMBERS_OF_ITERATIONS = 15000;

    public static void main(String[] args) {
        for (int i = 1; i < NUMBERS_OF_ITERATIONS; i++) {
            calculateSum(i);
        }
    }
}

我们在控制台可以看到非常多方法被内联了,我们找到我们关心的方法calculateSum

python 复制代码
288  395       4       org.example.inline.Main::calculateSum (12 bytes)
290  384       3       org.example.inline.Main::calculateSum (12 bytes)   made not entrant
                              @ 5   org.example.inline.Main$Sum::<init> (10 bytes)   inline (hot)
                                @ 1   java.lang.Object::<init> (1 bytes)   inline (hot)
                              @ 8   org.example.inline.Main$Sum::getTotalSum (25 bytes)   inline (hot)
  • 表示Main$Sum类的构造函数在字节码位置5处被内联,因为它是一个"hot"方法,即被频繁调用的方法。
  • 表示java.lang.Object类的构造函数被内联,因为它也是一个"hot"方法。
  • 表示getTotalSum方法在字节码位置8处被内联,原因同样是因为它是一个"hot"方法。

当方法被调用超过特定次数时,它会变为 "hot"。默认情况下,此阈值设置为 10,000

我们绝对不想内联所有内容,因为这会很耗时并且会产生一个巨大的字节码。

方法内联的优缺点

优势:

  • 减少函数调用的开销,提高执行速度。
  • 复制后的更大函数体为其他编译优化带来可能性,如 过程间优化
  • 消除分支,并改善空间局部性和指令顺序性,同样可以提高性能。

问题:

  • 代码复制带来的空间增长。
  • 如果有大量重复代码,反而会降低缓存命中率,尤其对 CPU 缓存是致命的。

参考文献: en.wikipedia.org/wiki/Inline...

相关推荐
掘金者阿豪38 分钟前
🚀 CentOS Stream 9服务器Docker部署KWDB:从零到跨模查询实战全记录
后端
yang_xin_yu44 分钟前
一文带你精通泛型PECS原则与四大核心函数式接口
后端
孟陬1 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
树獭叔叔1 小时前
13-KV Cache与位置编码表:大模型推理加速的核心技术
后端·aigc·openai
想用offer打牌1 小时前
一站式了解四种限流算法
java·后端·go
嘻哈baby1 小时前
用 C++ 写线程池是怎样一种体验?
后端
嘻哈baby1 小时前
SQL Server 和 Oracle 以及 MySQL 有哪些区别?
后端
绝无仅有1 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
武子康1 小时前
大数据-237 离线数仓 - Hive 广告业务实战:ODS→DWD 事件解析、广告明细与转化分析落地
大数据·后端·apache hive
绝无仅有1 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构