-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
An annotation to either prevent or force inlining of a function #2751
Comments
We very much shy away from annotations which direct optimizations. They tend to be major footguns. In general we'd like to improve the compiler heuristics around inlining. You can easily block inlining of a function with a sink value. Closure-Library has an example. Forcing inlining is a bit trickier. I don't have a good answer here. Perhaps @concavelenz has thoughts? |
Totally understand if that’s an intentional design decision 👍 Is the sink method you’re linking to all that different though? Perhaps it lifts the responsibility from GCC itself so it doesn’t feel like something you explicitly recommend. That makes sense to me. Is the exact approach it’s using more or less guaranteed to work in the future? |
It behaves exactly the same no matter which compiler passes are enabled. That's one of the major issues. |
The "noinline" annotation might be reasonable but I would like to understand a bit more how we break the heuristic by inlining. Is it not sufficient that the inlined code be inlined into monomorphic branch? Or do we end up de-duplicating the code branches and end up creating megamorphic code? We do have a knob to control how large a function inlining is allowed to create if it is overall function size that triggers the issue. I'm curious about the "inline" heuristic. Where does this actually help? It has been my assumption that with the modern VMs that they would do a better job of inlining for performance, and that we should only be inlining for code simplification. Or is this a case of code running without a JIT (react native?) |
From conversations among the team last week, it sounds like we're leaning toward implementing "noinline" but not implementing "force inline" |
It looks like we want to use |
|
Just FYI, I've started the work to add |
Followup changes will modify inlining passes to honor this annotation. Related to #2751 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179756574
Related to #2751 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179758969
Related to #2751 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179759191
I've now done enough work for |
Related to #2751 Not all of the Inline* passes honor the @noinline annotation yet, but this test shows that it basically works as expected in the common case. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179851747
hey guys, came here to open the same issue. my long-time work-around to prevent Closure's aggressive inlining has been to expose these functions in the is there any information as to why the JIT is negatively affected? i always assumed it's because the function hits a certain AST size threshold and the JIT simply bails on more advanced/expensive tracing. i remember back in the day when actual function character count was supposedly used as a de-opt heuristic (including whitespace and comments!) [2], [3]. [1] domvm/domvm#144 |
@leeoniya However, if your goal is just to prevent inlining in your code, I suggest you try using the I know that I didn't update every possible code path that could lead to inlining, but I believe I got most of them, so Also, if you're trying to prevent inlining because you expect your compiled code to be used from other JavaScript code, you should add |
thanks @brad4d,
also, not everything's exposed in the js version. ahem cheers! [1] google/closure-compiler-js#79 |
@leeoniya Most things are now the same between the GWT version and the Java version. For instance, trusted strings are now set true: https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/gwt/client/GwtRunner.java#L686 |
awesome! |
Since the |
We've been using GCC in the simple mode for compiling React for a few months, and are really happy with its heuristics. However, recently I've been noticing a minor pain point.
Problem
In some cases, as library authors we want to have more control over whether a function should be inlined or not. In particular, there are two scenarios:
Some functions are in a very hot path, and we have determined that not inlining them would hurt the runtime performance. Usually at this point we just inline them manually in the code. However, that often produces duplicate code that is hard to work with. Ideally, we'd love to have a way to tell GCC that it has to either inline a function or fail the build (if it’s impossible). This way we know that we won’t regress on this particular function.
There is an opposite problem as well. Sometimes we split a function into several to have tighter control over the argument types. For example, if some path is very hot, and we need to ensure a function is called with monomorphic arguments. However, GCC can break these optimizations by inlining the separated function (and thus preventing engines from optimizing that code due to deopts). For this use case, we'd like to have a way to tell GCC to not inline a function, even if the resulting code size will be larger.
Prior Art
The other GCC 🙂
inline
andalways_inline
noinline
Proposal
New
@inline
annotation forces inliningThis forces the function to be inlined even if the code size becomes bigger.
If it can’t be inlined, the build fails.
Alternative possible naming:
@always-inline
,@force-inline
.New
@noinline
annotation prevents inliningThis forces a function to never be considered for inlining, even if there is a size win.
Alternative possible naming:
@never-inline
,@prevent-inline
.Other hint formats?
I don't have a strong opinion about how to supply these hints. A comment, a JSDoc annotation, special function name, etc, would all work for me. Please let me know if this is something you would consider!
Current Workarounds
In case anyone’s curious, I’ve thought a bit about how to achieve this today.
Forcing inlining
There's no way to force inlining, but we could plausibly adopt a special naming convention (e.g.
*Inline
). We already have a special build where we disable the renaming pass (#2707) so we could analyze the bundle, and fail the build if any*Inline
function still exists. This wouldn’t force GCC to inline it, but at least we’d know if it was inlined but then started bailing.Preventing inlining
This file might contain some hints. For example attaching function to an object would prevent inlining that function.
Of course it would be nice to have an official solution for this, as both options are hacky and incomplete.
The text was updated successfully, but these errors were encountered: