Skip to content
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

Compile System.Private.CoreLib with Crossgen2 by default #44618

Merged
merged 3 commits into from
Nov 27, 2020

Conversation

trylek
Copy link
Member

@trylek trylek commented Nov 12, 2020

After I deleted the Utf8String-related experimental code from the
runtime repo per JanK's suggestion, I can now enable Crossgen2
compilation for System.Private.CoreLib by default.

Thanks

Tomas

/cc: @dotnet/crossgen-contrib

@trylek trylek added this to the 6.0.0 milestone Nov 12, 2020
@stephentoub
Copy link
Member

Does this have an impact on code quality, or is the before/after identical?

@trylek
Copy link
Member Author

trylek commented Nov 12, 2020

Our measurements so far indicate that Crossgen- and Crossgen2-compiled SPC should be almost identical with regards to runtime performance, working set and size on disk. Having said that, merging this commit will throw a much broader set of tests at the library so I cannot rule out some outlier popping up, that's why this change is intentionally trivial to revert. @mangod9 also suggested that I shoot a heads-up e-mail to the runtime repo committers once this goes in to help identify the cause of any issues that may appear.

@stephentoub
Copy link
Member

Ok, thanks.

@mangod9
Copy link
Member

mangod9 commented Nov 13, 2020

There appears to be a build failure on OSX?

@janvorli
Copy link
Member

The Linux x64 crossgen2 invocation failed. It has failed with an assert:

 Process terminated. Assertion failed.
  Please update intrinsic hash table
     at Internal.JitInterface.CorInfoImpl.InitializeIntrinsicHashtable() in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs:line 115
     at Internal.JitInterface.CorInfoImpl..cctor() in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.Intrinsics.cs:line 120
     at Internal.JitInterface.CorInfoImpl.ObjectToHandle(Object obj) in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs:line 421
     at Internal.JitInterface.CorInfoImpl.ObjectToHandle(MethodDesc method) in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs:line 439
     at Internal.JitInterface.CorInfoImpl.Get_CORINFO_METHOD_INFO(MethodDesc method, MethodIL methodIL, CORINFO_METHOD_INFO* methodInfo) in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs:line 455
     at Internal.JitInterface.CorInfoImpl.CompileMethodInternal(IMethodNode methodCodeNodeNeedingCode, MethodIL methodIL) in /_/src/coreclr/src/tools/Common/JitInterface/CorInfoImpl.cs:line 147
     at Internal.JitInterface.CorInfoImpl.CompileMethod(MethodWithGCInfo methodCodeNodeNeedingCode) in /_/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs:line 391
     at ILCompiler.ReadyToRunCodegenCompilation.<ComputeDependencyNodeDependencies>b__26_0(DependencyNodeCore`1 dependency) in /_/src/coreclr/src/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs:line 500
     at System.Threading.Tasks.Parallel.<>c__DisplayClass33_0`2.<ForEachWorker>b__0(Int32 i)
     at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0`1.<ForWorker>b__1(RangeWorker& currentWorker, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)
     at System.Threading.Tasks.TaskReplicator.Replica`1.ExecuteAction(Boolean& yieldedBeforeCompletion)
     at System.Threading.Tasks.TaskReplicator.Replica.Execute()
     at System.Threading.Tasks.TaskReplicator.Replica.<>c.<.ctor>b__4_0(Object s)
     at System.Threading.Tasks.Task.InnerInvoke()
     at System.Threading.Tasks.Task.<>c.<.cctor>b__277_0(Object obj)
     at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
     at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
     at System.Threading.Tasks.Task.ExecuteEntryUnsafe(Thread threadPoolThread)
     at System.Threading.Tasks.Task.ExecuteFromThreadPool(Thread threadPoolThread)
     at System.Threading.ThreadPoolWorkQueue.Dispatch()
     at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

@janvorli
Copy link
Member

The win x86 and OSX x64 too

@trylek
Copy link
Member Author

trylek commented Nov 13, 2020

Got it, @EgorBo's change

819a3cc#diff-ff19628c24a151a3f919c197c4785be0c9b10fa61f2e61beb4e4867b676dcc8c

removed two intrinsics without updating the assertion check at

Debug.Assert((int)CorInfoIntrinsics.CORINFO_INTRINSIC_Count == 34, "Please update intrinsic hash table");

I'll send out the fix as a separate PR to keep this switch-over PR trivial to rollback.

@trylek
Copy link
Member Author

trylek commented Nov 13, 2020

PR is out: #44624

@AndyAyersMS
Copy link
Member

Before you merge, it would be good for @DrewScoggins to verify we're not seeing any perf lab outage, so if we see any regressions we have a dense set of runs to help pin down which change is responsible.

@trylek
Copy link
Member Author

trylek commented Nov 13, 2020

I've booked vacation from Friday till next Tuesday. Assuming I manage to check in the fix for the assertion check tomorrow morning before I leave, I would be probably inclined to check this in on Saturday or Sunday - this should hopefully also make it easier to identify potential fallout of this change as the rate of check-ins is usually lower over the weekend.

trylek added a commit to trylek/runtime that referenced this pull request Nov 13, 2020
@trylek
Copy link
Member Author

trylek commented Nov 13, 2020

Currently lab testing in an instrumented run including the fix for the assertion check: #44625

@AndyAyersMS
Copy link
Member

cc @dotnet/jit-contrib

Please make sure there's a good writeup somewhere on how to repro and debug crossgen2 errors (particularly what happens if the jit asserts or crashes, and how to pass complus settings), as the first problems a jit developer often sees with new jit code surface during the crossgen of SPC that's done by the build.

We also need to make sure PMI, SPMI, and our automated SPMI collection processes are ready. @sandreenko weren't you looking at this recently?

@mangod9
Copy link
Member

mangod9 commented Nov 13, 2020

@AndyAyersMS crossgen2 has been validated with various weekly CI jobs, this change essentially now compiles s.p.corelib.dll by default. Is your concern mainly that there are going to be some JIT failures which might be difficult to debug? Regardless we can certainly get a runbook created for debugging steps.

@MichalStrehovsky
Copy link
Member

The Linux x64 crossgen2 invocation failed. It has failed with an assert:

Btw, I still have #43017 out to make the Checked build actually different from a Release build and have asserts fire consistently. I need a signoff to merge, but I guess we need to fix the regression first.

@DrewScoggins
Copy link
Member

@trylek Could you just comment out the line pr: none in https://github.com/dotnet/runtime/blob/master/eng/pipelines/coreclr/perf.yml. This way we can run through the performance tests to make sure that none of them are broken by this change. You can then remove the comment before you check-in.

@mangod9
Copy link
Member

mangod9 commented Nov 13, 2020

@DrewScoggins, I have pushed the change to run perf scenarios.

@mangod9 mangod9 self-requested a review November 13, 2020 18:00
@AndyAyersMS
Copy link
Member

Is your concern mainly that there are going to be some JIT failures which might be difficult to debug

@mangod9 because the newly built jit runs during the crossgen steps of the build, changes to the jit can cause build failures. So often the first debugging one does as part of changing the jit is to fix the issues that arise during crossgen. You often have to do this before running simple tests, if that step of the build can't easily be bypassed. Since the crossgen run is kicked off by the build it may not be easy to figure out how to repro and understand these failures by say running the same thing under the debugger.

Thus it's essential that the debugging experience be well documented, eg what command lines are needed, how to specify which jit is being invoked, how to tunnel through the complus settings that are useful when investigating jit issues.

We also often use crossgen for estimating throughput of jit changes. I suspect this is not going to work very well anymore with crossgen2, but we'll have to see.

@mangod9
Copy link
Member

mangod9 commented Nov 13, 2020

Thus it's essential that the debugging experience be well documented, eg what command lines are needed, how to specify which jit is being invoked, how to tunnel through the complus settings that are useful when investigating jit issues.

Yeah thats fair. We will work on putting these together.

@mangod9 mangod9 added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Nov 13, 2020
@sandreenko
Copy link
Contributor

SPMI is ready for crossgen2, not sure if we have jitutils support for it to do asm diffs.

However, the debugging experience with crossgen2 was worse than crossgen for me in the past, because:

  1. was not clear how to compile as simple as "crossgen.exe target.dll", instead, you need to know how to create a right ".rsp" file and use it;
  2. passing COMPlus_* variables is harder for debugging, you need to pass them as --codegenopt NgenDump=Repro.Program:Main in the command line and if I remember correctly some were not working (for example Dump).

@mangod9
Copy link
Member

mangod9 commented Nov 13, 2020

@DrewScoggins could you please check the Linux x64 runtime-perf failures, if they are perf related?

@erozenfeld
Copy link
Member

SPMI is ready for crossgen2, not sure if we have jitutils support for it to do asm diffs.

I added support for asm diffs with crossgen2 a year ago in dotnet/jitutils#228 and dotnet/jitutils#234. It may need to be tweaked if crossgen2 command line args have changed since then. Also, we'll probably need to control crossgen2 multithreading.

@kunalspathak
Copy link
Member

Curious, how do we see the perf results?

@DrewScoggins
Copy link
Member

These results are not saved, nor are they even applicable. These tests just run the tests on VMs for a single iteration to ensure that they have not been broken by the change, not to investigate regressions or improvements.

@trylek
Copy link
Member Author

trylek commented Nov 26, 2020

The OSX x64 failure is known, #45088.

@trylek
Copy link
Member Author

trylek commented Nov 26, 2020

OK, after one retry the PR run is green now. I have triggered the outerloop run and I intend to merge this in tomorrow European morning (around PST midnight) assuming it reasonably passes and no-one objects. I believe this to be the perfect moment - around Thanksgiving the traffic is pretty low so any potential regression will stand out. As discussed previously, I'll send a heads-up e-mail to the runtime repo committers to watch out for any weird behavior after the merge. Thanks everyone for help with various aspects of this change!

@mangod9
Copy link
Member

mangod9 commented Nov 26, 2020

sounds like a good plan. Thanks @trylek

@mangod9 mangod9 removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Nov 26, 2020
trylek and others added 3 commits November 27, 2020 09:10
After I deleted the Utf8String-related experimental code from the
runtime repo per JanK's suggestion, I can now enable Crossgen2
compilation for System.Private.CoreLib by default.

Thanks

Tomas
This reverts commit 01c1559872a322469eeceb8bea9084a1d104bc2f.
@trylek trylek merged commit b79e4d3 into dotnet:master Nov 27, 2020
@trylek trylek deleted the Crossgen2CorelibByDefault branch November 27, 2020 15:21
@am11
Copy link
Member

am11 commented Nov 27, 2020

Other than the file size regression, crossgen2 is great! 🙂

# ubuntu x64
$ ./build.sh -c Release
$ du -h artifacts/bin/coreclr/Linux.x64.Release/System.Private.CoreLib.dll

# before
8.9M	artifacts/bin/coreclr/Linux.x64.Release/System.Private.CoreLib.dll
# after
9.6M	artifacts/bin/coreclr/Linux.x64.Release/System.Private.CoreLib.dll

@trylek
Copy link
Member Author

trylek commented Nov 27, 2020

Thanks @am11 for pointing that out, I'll take a look. That is surprising as the last time I looked, the CG2 version was actually shorter.

@trylek
Copy link
Member Author

trylek commented Nov 27, 2020

OK, so I took a first look using the R2RDump --diff function. I tried this on Windows x64 as there's basically no size difference between the Windows and Linux version (the only actual difference being slightly different calling convention implying subtle changes in some JITted method lengths). The total difference is about 850 KB; almost half of this delta, 380 KB, corresponds to the section DelayLoadMethodCallChunks - in the CG1 version this section only has 33 bytes. @janvorli - am I right to recall it was you who implemented this section? Is it possible that CG1 uses some more compact encoding e.g. by representing all thunks with a single coalesced interval? Supporting this may require putting the thunks into a subsection of its own, implying subtle tweaks to the object writer but the section builder does support this in general, it should be no big deal. I'm looking for the other half that's currently not accounted for by R2RDump for whatever reason.

@janvorli
Copy link
Member

. @janvorli - am I right to recall it was you who implemented this section?

No, it was @nattress in #39063

stephentoub added a commit to stephentoub/runtime that referenced this pull request Nov 29, 2020
danmoseley pushed a commit that referenced this pull request Nov 30, 2020
)" (#45320)

* Revert "Compile System.Private.CoreLib with Crossgen2 by default (#44618)"

This reverts commit b79e4d3.

* Add a change to ensure libraries are built/tested
@ghost ghost locked as resolved and limited conversation to collaborators Dec 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.