java 什么是内联?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1546694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is inlining?
提问by Roger
I am referring to this discussion. I have never written any code in C or in C++ . I do not have any CS background. However I have been working as Java developer for 5 years and now I have decided to learn more about CS and do some catching up.
我指的是这个讨论。我从未用 C 或 C++ 编写过任何代码。我没有任何 CS 背景。然而,我作为 Java 开发人员已经工作了 5 年,现在我决定更多地了解 CS 并进行一些追赶。
回答by JohnIdol
When executing a given piece of code, whenever you call a standard function the execution time is slightly higher than dumping there the code contained into that function. Dumping every time the whole code contained in a function is on the other end unmainteinable because it obviously leads to a whole mess of duplication of code.
在执行一段给定的代码时,无论何时调用标准函数,执行时间都比将包含在该函数中的代码转储到那里略长。每次转储包含在函数中的整个代码在另一端是不可维护的,因为这显然会导致一团糟的代码重复。
Inliningsolves the performance and maintainability issue by letting you declare the function as inline(at least in C++), so that when you call that function - instead of having your app jumping around at runtime - the code in the inline function is injected at compile time every time that given function is called.
通过让您将函数声明为内联(至少在 C++ 中),内联解决了性能和可维护性问题,这样当您调用该函数时 - 而不是让您的应用程序在运行时跳转 - 内联函数中的代码在编译时注入每次调用给定函数时的时间。
Downside of this is that - if you inline big functions which you call a lot of times - the size of your program may significantly increase (best practicessuggest to do it only on small functions indeed).
这样做的缺点是 - 如果您内联多次调用的大函数 - 程序的大小可能会显着增加(最佳实践建议确实只在小函数上执行此操作)。
回答by George
http://en.wikipedia.org/wiki/Inlining
http://en.wikipedia.org/wiki/Inlining
In computing, inline expansion, or inlining, is a compiler optimization that replaces a function call site with the body of the callee. This optimization may improve time and space usage at runtime, at the possible cost of increasing the size of the final program.
在计算中,内联扩展或内联是一种编译器优化,它用被调用者的主体替换函数调用站点。这种优化可能会提高运行时的时间和空间使用率,但可能会增加最终程序的大小。
回答by Michael Borgwardt
As a Java developer, you generally don't have to worry about method inlining. Java's Just-in-time compiler can and will do it automatically in most places where it makes sense.
作为 Java 开发人员,您通常不必担心方法内联。Java 的 Just-in-time 编译器可以并且将会在大多数有意义的地方自动执行。
IDEs like eclipse can have a feature that allows you to inline methods at the source code level - neverdo this for performance, only for code readability (e.g. when you realize that the method just calls one other method without adding anything useful itself).
像 Eclipse 这样的 IDE 可以有一个特性,允许您在源代码级别内联方法 -永远不要为了性能而这样做,只是为了代码可读性(例如,当您意识到该方法只是调用另一个方法而不添加任何有用的东西时)。
回答by emre ozcan
Norman Maurerexplains at his blogJVM and JIT inline functionality like that
Norman Maurer在他的博客中解释了这样的JVM 和 JIT 内联功能
Inlining is a technique that will basically just "inline" one method in another and so get rid of a method invocation. The JIT automatically detects "hot" methods and try to inline them for you.A method is considered "hot" if it was executed more the X times, where X is a threshold that can be configured using a JVM flag when start up java (10000 is the default). This is needed as inlining all methods would do more harm then anything else, because of the enormous produced byte-code. Beside this the JIT may "revert" previous inlined code when an optimization turns out to be wrong at a later state. Remember the JIT stands for Just in Time and so optimize (which includes inlining but also other things) while execute your code.
内联是一种技术,它基本上只是将一个方法“内联”到另一个方法中,因此摆脱了方法调用。JIT 会自动检测“热”方法并尝试为您内联它们。如果某个方法执行次数超过 X 次,则该方法被认为是“热的”,其中 X 是一个阈值,可以在启动 java 时使用 JVM 标志进行配置(默认值为 10000)。这是必要的,因为内联所有方法会比其他任何方法造成更大的伤害,因为产生了巨大的字节码。除此之外,当优化在以后的状态中被证明是错误的时,JIT 可能会“恢复”以前的内联代码。请记住,JIT 代表 Just in Time,因此在执行代码时会进行优化(包括内联和其他内容)。
Also with a warning
也有警告
But even if the JVM consider a method to be "hot" it may not inline it. But why? One of the most likely reasons is that it is just to big to get inlined.
但即使 JVM 认为一个方法是“热的”,它也可能不会内联它。但为什么?最可能的原因之一是内联太大了。
And you can find a very simple code example for inlining a Java code at Eva Andreasson's Java World Post. You can find the related part of post at below.
您可以在Eva Andreasson的 Java World Post 上找到一个非常简单的代码示例,用于内联 Java 代码。您可以在下面找到帖子的相关部分。
Many optimizations try to eliminate machine-level jump instructions (e.g., JMP for x86 architectures). A jump instruction changes the instruction pointer register and thereby transfers the execution flow. This is an expensive operation relative to other ASSEMBLY instructions, which is why it is a common target to reduce or eliminate. A very useful and well-known optimization that targets this is called inlining.Since jumping is expensive, it can be helpful to inline many frequent calls to small methods, with different entry addresses, into the calling function. The Java code in Listings 3 through 5 exemplifies the benefits of inlining.
许多优化尝试消除机器级跳转指令(例如,用于 x86 架构的 JMP)。跳转指令改变指令指针寄存器,从而转移执行流程。相对于其他 ASSEMBLY 指令,这是一项代价高昂的操作,这就是为什么它是减少或消除的常见目标的原因。针对此的一个非常有用且众所周知的优化称为内联。由于跳转的开销很大,因此将许多对具有不同入口地址的小方法的频繁调用内联到调用函数中会很有帮助。清单 3 到 5 中的 Java 代码举例说明了内联的好处。
Listing 3. Caller method
清单 3. 调用者方法
int whenToEvaluateZing(int y) {
return daysLeft(y) + daysLeft(0) + daysLeft(y+1);
}
Listing 4. Called method
清单 4. 被调用的方法
int daysLeft(int x){
if (x == 0)
return 0;
else
return x - 1;
}
Listing 5. Inlined method
清单 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;
}
In Listings 3 through 5 the calling method makes three calls to a small method, which we assume for this example's sake is more beneficial to inline than to jump to three times.
It might not make much difference to inline a method that is called rarely, but inlining a so-called "hot" method that is frequently called could mean a huge difference in performance. Inlining also frequently makes way for further optimizations, as shown in Listing 6.
在清单 3 到 5 中,调用方法对一个小方法进行了 3 次调用,为了这个例子,我们假设这对内联比跳转到 3 次更有好处。
内联一个很少调用的方法可能没有太大区别,但是内联一个经常调用的所谓“热”方法可能意味着性能上的巨大差异。内联还经常为进一步优化让路,如清单 6 所示。
Listing 6. After inlining, more optimizations can be applied
清单 6. 内联后,可以应用更多优化
int whenToEvaluateZing(int y){
if(y == 0) return y;
else if (y == -1) return y - 1;
else return y + y - 1;
}
回答by hlovdal
As already mentioned in other answers, inlining comes with a cost. Usually this is considered small, however when actually measuring you might be surprised and learn that it might be greater than what you gain (so what other people sayis true: do not optimize unless you have measured).
正如其他答案中已经提到的,内联是有成本的。通常这被认为很小,但是在实际测量时,您可能会惊讶并发现它可能比您获得的更大(所以其他人说的是对的:除非您已经测量,否则不要优化)。
It is worth noting that in the Linux kernel they started un-inlining originally inlined functions some time ago because the cost was too high (larger functions consumed more of the cpu memory cache, and the resulting cache misses were more expensive than just calling the function that were intended to be inlined). See "Chapter 15: The inline disease" in doc/Documentation/process/coding-style.rstfor more details.
值得注意的是,在Linux内核中他们前段时间开始un-inline原本内联的函数,因为成本太高(较大的函数消耗了更多的cpu内存缓存,由此产生的缓存未命中比仅仅调用函数更昂贵旨在内联)。有关更多详细信息,请参阅doc/Documentation/process/coding-style.rst 中的“第 15 章:内联疾病” 。
回答by TrueWill
The compiler optimization answers are correct. There is another usage, though - in refactoring, inlining refers to replacing a method call with the body of the method and then removing the method. See Inline Method. There are similar refactorings, such as Inline Class.
编译器优化答案是正确的。但是,还有另一种用法 - 在重构中,内联是指用方法体替换方法调用,然后删除该方法。请参阅内联方法。还有类似的重构,比如Inline Class。
EDIT: Note that refactoring is done manually or with a tool; in either case it involves changing the source code.
编辑:请注意,重构是手动或使用工具完成的;在任何一种情况下,它都涉及更改源代码。
回答by James Black
Basically, in C/C++, the compiler can inline functions, which means that rather than making a function call to do that operation, the code will be added to the calling function's block, so it will be as though it had never been a separate function call.
基本上,在 C/C++ 中,编译器可以内联函数,这意味着不是进行函数调用来执行该操作,而是将代码添加到调用函数的块中,因此就好像它从来没有分开过函数调用。
This will go into more detail: http://www.codersource.net/cpp_tutorial_inline_functions.html
这将更详细:http: //www.codersource.net/cpp_tutorial_inline_functions.html
回答by kwcto
Inlining refers to compile-time optimization where a small function of code will be injected into the calling function rather than require a separate call.
内联是指编译时优化,其中将一小部分代码注入调用函数中,而不需要单独调用。
回答by BrentAllenParrish
Inline functions are used typically in C++ header files not Java. A C++ header file usually does not contain implemented code and is considered an interface to the cpp file of the same name, which does usually contain the implemented code. It is legal to include an inline function in a header file, usually a small lightweight function. Inline functions do come at a cost, so they should not be large memory-intensive operations. For small routines the performance hit is minimal and they are more used for convenience.
内联函数通常用于 C++ 头文件而不是 Java。C++ 头文件通常不包含已实现的代码,被认为是同名 cpp 文件的接口,该文件通常包含已实现的代码。在头文件中包含内联函数是合法的,通常是一个小的轻量级函数。内联函数确实需要付出代价,因此它们不应该是大量内存密集型操作。对于小型例程,性能影响很小,它们更多地用于方便。
回答by Nicholas Jordan
In that discussion, Jon Skeet mentions Client jvm (hotspot) v Server jvm with the performance improvements available at run-time if the JIT ( just-in-time ) compiler is allowed to bring time-based enhancements. That is "how it's done" in Java.
在该讨论中,Jon Skeet 提到了客户端 jvm(热点)v 服务器 jvm,如果允许 JIT(即时)编译器带来基于时间的增强,则在运行时可以获得性能改进。这就是 Java 中的“如何完成”。
Originally, small sections of code that were not called from many places would be "inlined" by the compiler, meaning that what was called a singleton would be placed directly in the instruction pointer code path, doing a function branch and return costs more processor power than just unrolling to loop or function call and placing the instructions "right there"
最初,没有从很多地方调用的小部分代码会被编译器“内联”,这意味着所谓的单例将直接放置在指令指针代码路径中,执行函数分支和返回会消耗更多的处理器能力不仅仅是展开循环或函数调用并将指令“就在那里”
Today, Singleton is the subject of multi-page discussions and loop-unrolling as well as something like inlining are somewhat removed from their original context(s). You can read Dov Bulka's very informed work on the matter to get the C/C++ take on the matter. For Java, study of it's rich lib's in java.util would better serve your needs than study of inlining and deep compiler issues - you can get hung on entrenched embattled intramural warfare on data structures, which gloss over calls into 16-bit code, and go no end on your learning curve.
今天,单例是多页讨论的主题,循环展开以及内联之类的东西在某种程度上脱离了它们的原始上下文。您可以阅读 Dov Bulka 关于此事的非常有见地的工作,以了解 C/C++ 对此事的看法。对于 Java,研究 java.util 中丰富的 lib 比研究内联和深度编译器问题更能满足您的需求——您可能会沉迷于数据结构上根深蒂固的壁垒战,它掩盖了对 16 位代码的调用,并且在您的学习曲线上永无止境。
You can do instanceof in Java, that resembles a vf-table ( no heat folks, please ) but think of it as you have been writing in a strongly typed language - and now will be writing in a language where string can runaway easily poking around where it has no business. I recently tried to write code that constructed an Image in Java, doing that from C code. I soon found myself looking at the oxr table for strong encryption - that has nothing to do with the code I was writing.
您可以在 Java 中执行 instanceof,它类似于 vf 表(请不要热心的人),但可以将其想象为您一直在使用强类型语言编写 - 现在将使用一种字符串可以很容易地乱窜的语言编写它没有业务的地方。我最近尝试编写在 Java 中构造图像的代码,从 C 代码中完成。我很快发现自己正在查看 oxr 表以进行强加密 - 这与我正在编写的代码无关。
How would you write a string class in C/C++ that has a small buffer for strings under 32 bytes and traps pointers so that they only operate on the string?
您将如何在 C/C++ 中编写一个字符串类,它为 32 字节以下的字符串提供一个小缓冲区并捕获指针,以便它们只对字符串进行操作?
Not trying to tease you or anything, it's just a really good place to start rather than inlining and compiler science.
不是试图取笑你或任何东西,它只是一个非常好的起点,而不是内联和编译器科学。

