Joh*_*dol 41
执行给定的代码时,无论何时调用标准函数,执行时间都略高于将函数转储到该函数中的代码.每次函数中包含的整个代码在另一端的转储都是不可维护的,因为它显然会导致代码重复的混乱.
内联通过让您将函数声明为内联(至少在C++中)来解决性能和可维护性问题,这样当您调用该函数时 - 而不是让您的应用程序在运行时跳转 - 内联函数中的代码在编译时注入每次调用给定函数时的时间.
这样做的缺点是 - 如果你在很多时候内联大型函数 - 程序的大小可能会显着增加(最佳实践建议只在小函数上执行).
Geo*_*rge 13
http://en.wikipedia.org/wiki/Inlining
在计算,内联扩展或内联中,是一种编译器优化,它将函数调用站点替换为被调用者的主体.这种优化可以在运行时改善时间和空间使用,可能增加最终程序的大小.
作为Java开发人员,您通常不必担心方法内联.Java的Just-in-time编译器可以并且将在大多数有意义的地方自动执行.
像eclipse这样的IDE可以有一个功能,允许你在源代码级别内联方法 - 永远不要为性能而做,只为了代码可读性(例如当你意识到方法只调用另一个方法而不添加任何有用的东西).
小智 5
Norman Maurer在他的博客中解释了JVM 和 JIT 内联功能
内联是一种基本上只是将一个方法“内联”到另一个方法中的技术,从而消除方法调用。JIT 自动检测“热门”方法并尝试为您内联它们。如果一个方法被执行了 X 次以上,则该方法被认为是“热”的,其中 X 是启动 java 时可以使用 JVM 标志配置的阈值(默认值为 10000)。这是必要的,因为内联所有方法都会比其他任何方法造成更大的危害,因为产生了大量的字节码。除此之外,当优化在稍后的状态下被证明是错误的时,JIT 可能会“恢复”以前的内联代码。请记住,JIT 代表“及时”,因此在执行代码时进行优化(包括内联以及其他内容)。
还带有警告
但即使 JVM 认为某个方法是“热”的,它也可能不会内联它。但为什么?最可能的原因之一是它太大而无法内联。
您可以在Eva Andreasson的 Java World Post中找到用于内联 Java 代码的非常简单的代码示例。您可以在下面找到帖子的相关部分。
许多优化尝试消除机器级跳转指令(例如,用于 x86 架构的 JMP)。跳转指令改变指令指针寄存器,从而转移执行流程。相对于其他汇编指令,这是一个昂贵的操作,这就是为什么它是减少或消除的常见目标。针对此目标的一个非常有用且众所周知的优化称为内联。由于跳转的成本很高,因此将具有不同入口地址的对小方法的许多频繁调用内联到调用函数中会很有帮助。清单 3 到 5 中的 Java 代码举例说明了内联的好处。
清单 3. 调用者方法
int whenToEvaluateZing(int y) {
return daysLeft(y) + daysLeft(0) + daysLeft(y+1);
}
Run Code Online (Sandbox Code Playgroud)
清单 4. 调用的方法
int daysLeft(int x){
if (x == 0)
return 0;
else
return x - 1;
}
Run Code Online (Sandbox Code Playgroud)
清单 5. 内联方法
int whenToEvaluateZing(int y){
int temp = 0;
if(y == 0) temp += 0; else temp += y - 1;
if(0 == 0) temp += 0; else temp += 0 - 1;
if(y+1 == 0) temp += 0; else temp += (y + 1) - 1;
return temp;
}
Run Code Online (Sandbox Code Playgroud)
在清单 3 到 5 中,调用方法对一个小方法进行了三次调用,在本示例中我们假设这对内联比跳转三次更有利。
内联一个很少被调用的方法可能没有多大区别,但内联一个经常被调用的所谓“热”方法可能意味着性能上的巨大差异。内联还经常为进一步优化让路,如清单 6 所示。
清单 6. 内联后,可以应用更多优化
int whenToEvaluateZing(int y){
if(y == 0) return y;
else if (y == -1) return y - 1;
else return y + y - 1;
}
Run Code Online (Sandbox Code Playgroud)