-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Another RyuJIT optimization bug #4393
Comments
Andrey, thank you for the reduced repro. Your analysis is correct. I have a fix for the issue that is going through the bug fix processes. |
So the current blog entry from Microsoft is describing the tail call optimization defect and stating that it's okay to leave RyuJIT on in production and simply disable tail call optimization. Yet the above bug seems to indicate a new defect in RyuJIT code generation that contradicts the idea that RyuJIT is fine for production minus tail call optimization. Should the advice in the blog entry be updated based on the above? http://blogs.msdn.com/b/dotnet/archive/2015/07/28/ryujit-bug-advisory-in-the-net-framework-4-6.aspx |
Given the fact that there have been 2 such nasty bugs found so quickly, and the fact that ryujit isn't a huge performance boost, it looks like holding off on ryujit in general for a while looks like better advice than merely disabling tail calls. |
Agree. Updating a blog post is also not enough. There needs to be an update on the existing blog post and a general announcement which clearly says: DO NOT USE IN PRODUCTION. |
@EamonNerbonne, I completely agree. In my humble opinion, RyuJIT is not ready yet. |
@EamonNerbonne that is without counting subpar optimization on other pretty common performance sensitive scenarios. |
Its important to realize that RyuJIT's primary prupose is that it is lighter and faster in running. It will optimize your code more quickly. As a JITer, it will not perform some of the complex optimizations that x64-JIT performed, which was based on the C++ AoT compiler. See: http://blogs.msdn.com/b/dotnet/archive/2013/09/30/10453200.aspx Missed optimization opportunities are absolutely issues that should be talked about to make RyuJIT even better, but just do realize that the comparison to x64 is unfair. RyuJIT gets you to a JITed state faster, reduces startup times on server applications and long-running services, etc. There is indeed a trade-off and it was well documented. |
But for long running systems, it is fine to have a bit slower startup time *Hibernating Rhinos Ltd * Oren Eini* l CEO l *Mobile: + 972-52-548-6969 Office: +972-4-622-7811 *l *Fax: +972-153-4-622-7811 On Wed, Jul 29, 2015 at 5:21 PM, Eyas notifications@github.com wrote:
|
@Eyas probably but if you release it as the default the expectations are that it is on-par on what you already have.
Let's agree to disagree. While it makes sense, I dont share the feeling that is true. What's the point of being able to startup 5-10 seconds earlier if you are going to lose minutes/hours over the time the application is processing (and forced it even on my old applications that do not target 4.6)? This is definitely something to discuss in a different issue though. I stand on the position that in the current state RyuJIT is not ready for being the default. |
@redknightlois Yep, I'm not affiliated with Microsoft in any way. Just expressing that the RyuJIT decision was announced in 2013 and made probably before that. The blog post makes the case that they intend to make. Their proposition is that RyuJIT is already better for most use cases. Another issue might be appropriate for a larger discussion about what kinds of optimizations RyuJIT should and shouldn't be doing, that Legacy-JIT performed previously. Fine by me. But what I'm trying to prevent is having every "regression" issue devolving into a conversation about "RyuJIT is worse, how are they releasing this?" when our metric for "worse" is not the one they are using. Edit: to clarify, We should track performance regressions, just not degrade the conversation |
I would argue that as the users, our metric for worse is the one that count. *Hibernating Rhinos Ltd * Oren Eini* l CEO l *Mobile: + 972-52-548-6969 Office: +972-4-622-7811 *l *Fax: +972-153-4-622-7811 On Wed, Jul 29, 2015 at 5:42 PM, Eyas notifications@github.com wrote:
|
@ayende is absolutely right here. The longer the program is going to run, the more important performance becomes, rather than startup time. |
@ayende Possibly. But that is the topic of another ticket/discussion about a larger issue with what RyuJIT is even trying to solve. |
I'm more concerned with generated code correctness before I start load testing my app with the new JIT. I am still excited by RyuJIT overall, but this has been released into prod with two codegen defects (so far), and the blog post about the first defect doesn't advise you to avoid the second. I don't know if there's a technical reason why they defaulted pre-4.6 assemblies to using RyuJIT but I think that was the real mistake here. People don't expect a framework upgrade to break their not-yet-upgraded projects. |
…assignment GitHub Issue: Another RyuJIT optimization bug #1299 https://github.com/dotnet/coreclr/issues/1299 The underlying problem is there are two loops: The first loop does copy prop The second loop updates the stack of live definitions in the currently traversed CFG path. This approach works fine only if assignments are atomic statements, but when there is an assignment embedded using a comma in a statement: The first loop does nothing about this and continues to propagate copies, i.e., without updating the liveness stack. This leads to using a stale VN for comparison rather than using an updated VN due to this definition. Only when the second loop runs, this live definition is added to the stack. The right fix is to merge the two loops into a single loop that does copy prop on the tree and at the same time updates the liveness on the stack right after the call. But this is causing a lot of ASM diffs which would affect stability. I am making a conservative fix of temporarily marking the variables that have embedded intervening defs as "killed", until the second loop runs to update liveness. There are no SuperASM diffs with this change.
This issue based on a SO question: RyuJit producing incorrect results.
Example 1
Let's start with the following simple code:
The expected result:
The actual RyuJIT result:
It was reproduced with .NET 4.6 Release RyuJIT (x64, Release build) and CoreCLR RyuJIT 480227b. Let's look to the asm.
We can see that RyuJIT transforms source
to
It is wrong.
Example 2
The expected result:
The actual RyuJIT result:
We can see that RyuJIT apply an optimization wrong way only first time. Let's look to the asm.
We can see that RyuJIT transforms source
to
but only for the first call. It is wrong result. For the second call we have
It is ok.
Conclusion
It seems that there is a tricky RyuJIT optimization bug which depends on big amount of additional conditions: any changes of the source code spoil reproducibility.
The text was updated successfully, but these errors were encountered: