-
Notifications
You must be signed in to change notification settings - Fork 21
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
Attribute to prevent fsc inlining but allow JIT inlining #838
Comments
It seems that I am no longer alone with the F# performance feature requests! While I have limited time, I am happy to help. |
When you say "prevent fsc inlining", do you mean explicit inline through But in either case, these are source inlinings, and preventing these could lead to different signatures, and automatic overloads not overloading anymore (ie, the functions would be fixed). Assuming it's something else, what kind of inlinings are you talking about here? Not JIT inlining, so there must be something else. Do you have an example? |
Another example when it's needed. |
@buybackoff, I don't follow, as the function here is marked inline. Can you elaborate how this would help? Btw, we already have a let inline private asNode(value:MapTree<'Key,'Value>) : MapTreeNode<'Key,'Value> =
// F# is "too smart" and eliminates the inlined IL call, but that should be left to JIT, otherwise stuff breaks
// (# "ret" value: MapTreeNode<'Key,'Value> #)
// Ideally we need ldarg.0;ret without S.R.CS.U dependency
// :?> also works, but it's not free, while the usage guarantees correct unsafe casts
// when this is implemented, S.R.CS.U could be removed for inline IL: https://github.com/fsharp/fslang-suggestions/issues/838
// Unsafe.As<MapTreeNode<'Key,'Value>>(value)
value :?> MapTreeNode<'Key,'Value> // this is not visible for performance |
@abelbraaksma it's market as If we were to use Currently, F# inlines a method with only For JIT such a method with |
@buybackoff Sounds to me that instead the inline algorithm needs fixing, if code can break. It's probably due to the inline IL syntax, which iirc, gets treated differently in the inline functions compared to normal source code. Interesting that both versions get inlined, but one causes failed execution. Perhaps it's not the inlining that goes bersirk, but the optimization algorithm, which eliminates redundant IL. |
Btw, do I understand you correctly that if you remove |
I think this is the case, but in the context of this issue is an example when a new F# attribute is useful. If I add |
In that case F# still inlines it, because it's small. A workaround like this would prevent inlining when it's actually useful. |
So, I gather that |
Exactly |
Please note, the new CoreCLR have profile guided optimization as of dotnet/runtime#42277. The JIT can make decisions based on the actual execution profile. For example a small tight code that called in a loop - especially when the generated code fits in the instruction decoding cache - could be really fast, could be lot faster than than the flattened code without loop (dotnet/fsharp#5178 (comment)) . |
This maybe better placed there, but logically this is grouped here for high performance IL/JIT tweaks. Currently, F# adds E.g. in some pseudo-language
A new attribute such as You could see what performance gains are possible for primitives in this Map and Set PRs. But even for them, I had to use struct ctor instead of a method, because F# does not add In that case, performance for reference types regressed probably due to additional non-inlined wrapper call. If this theory is right then we could get huge performance increase for known types and keep the performance for other types exactly the same. Together with the attribute from this issue it will let to control IL and inlining behavior for hot paths much better. I could open a separate suggestion, but IMO they should go together. (Hopefully as a part of .NET 6 🙏) @AndyAyersMS Could you, please, confirm that |
Yes. There are two aspects of this:
The reason for the restrictions above is that proper handling of We've recently made the helpers faster and more uniform across all ABIs and ISAs, and we may be able to revisit this policy in the future. See for example dotnet/runtime#12304 |
Thank you for insight, @AndyAyersMS! I did not notice the issue dotnet/fsharp#6329 before, my comment is a dupe of it. |
Marking as approved-in-principle. It would be great to have this as a community-led contribution |
Completed. |
This will need a small RFC describing the theory how it works. For any future references. |
@kerams can we also document here and in the rfc with a small example what the attribute is and how it works? |
Here, hope it's sufficient. @abelbraaksma, it's really simple. Slap the attribute on any value, function or method and it won't be inlined in IL. |
Perfect! Thanks. Awesome work on the PR, btw! I was curious about this in particular, which you answered there:
|
Not sure why this was never closed. This is now part of F# 7.0 and up. |
I don't think this ever became a suggestion
dotnet/fsharp#5178
@dsyme called it a reasonable request
dotnet/fsharp#5178 (comment)
Pros and Cons
The advantages of making this adjustment to F# are:
Separate JIT and fsc inlining directives better
The disadvantages of making this adjustment to F# are:
Nothing substantial
Extra information
Estimated cost (XS, S, M, L, XL, XXL): XS
Related suggestions: (put links to related suggestions here)
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
The text was updated successfully, but these errors were encountered: