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

Need to figure out what to do with ILLink in source-build #580

Closed
eerhardt opened this issue May 30, 2018 · 30 comments
Closed

Need to figure out what to do with ILLink in source-build #580

eerhardt opened this issue May 30, 2018 · 30 comments
Assignees
Labels
area-prebuilts Reducing the number of prebuilt packages in the tarball area-product-experience Improvements in the end-user's product experience

Comments

@eerhardt
Copy link
Member

Today, we turn off ILLink in corefx

<BuildCommand>$(ProjectDirectory)/build$(ShellExtension) $(BuildArguments) -- /p:ILLinkTrimAssembly=false</BuildCommand>

But we are now dependent on ILLink with #376.

We should either not use ILLink at all. Or we should embrace it everywhere and figure out how to build it from source (it depends on Mono.Cecil), and then use that source-built version to build .NET Core.

/cc @weshaggard @dagood @dseefeld

@tmds
Copy link
Member

tmds commented Jun 4, 2018

@eerhardt I know corefx is using illink for avoiding zeroing stackalloced memory. Is it is used for other things?

@eerhardt
Copy link
Member Author

eerhardt commented Jun 4, 2018

dotnet/coreclr appears to be using it to build System.Private.CoreLib - probably for the same reasons corefx does.

I'm not 100% sure where else. @dagood - I didn't see any reasoning in #376 why ILLink.Tasks was added. Can you explain why the dependency got added here?

@weshaggard
Copy link
Member

@erozenfeld @stephentoub any thoughts on implications of turning this off our source-builds?

@stephentoub
Copy link
Member

stephentoub commented Jun 7, 2018

appears to be using it to build System.Private.CoreLib - probably for the same reasons corefx does.

Yes, both coreclr and corefx use the linker to trim away dead code and to avoid zero'ing locals. (Though it appears from your initial comment the trimming was turned off for corefx... I wasn't aware of that. I know I've had cases in recent memory where things got trimmed away, so I'm not sure what's going on, maybe it's a very recent change? Or... maybe that's just for source build?)

Implications of turning off the linker would be larger binaries and less-efficient code; in particular for corelib, the latter was very measurable in various microbenchmarks around things like string processing, integer formatting and parsing, etc., things involving sizeable stackallocs.

Once https://github.com/dotnet/csharplang/blob/master/proposals/skip-localsinit.md is available in the compiler, we can use that instead of the linker, at least for the locals zero'ing.

@eerhardt
Copy link
Member Author

eerhardt commented Jun 7, 2018

Dumb question about trimming dead code - now that we’ve brought back all the APIs in netstandard2.0, can’t we just delete any remaining dead code? Or at least #if it out for .NET Core?

@stephentoub
Copy link
Member

can’t we just delete any remaining dead code?

For the most part, yes, and it's in progress:
https://github.com/dotnet/corefx/issues/17905

@erozenfeld
Copy link
Member

Yes, ILLink is currently used only for trimming code and clearing initlocals. Note that some dead things can't be removed from source but can be removed by ILLink: e.g., inlined constants, private constructors. ILLink is also a place for any other future IL-to_IL transformations that either can't be done by Roslyn or can be done by Roslyn but may benefit from first testing them in ILLink (like we did with clearing initlocals). Having ILLink in the corefx and coreclr pipelines is convenient for that.

@sbomer and I have been building ILLink.Tasks from source (including Cecil) and publishing the packages. We can help with integrating that into source-build if that is what is required. Is source build not allowed to use any packages?

@erozenfeld
Copy link
Member

@jeffschwMSFT @jkotas

@dagood
Copy link
Member

dagood commented Jun 7, 2018

@dagood - I didn't see any reasoning in #376 why ILLink.Tasks was added. Can you explain why the dependency got added here?

With the BuildTools and CoreCLR update, the package not existing made CoreCLR fail, and the priority was getting CoreCLR working. I didn't get a deep understanding of why it wasn't needed before and was after.

@dseefeld dseefeld added triaged area-prebuilts Reducing the number of prebuilt packages in the tarball labels Jun 8, 2018
@tmds
Copy link
Member

tmds commented Jun 11, 2018

@eerhardt @dagood My understanding from this issue is that ILLink packages are being fetched, but they are not being used. Is that correct?

@dagood
Copy link
Member

dagood commented Jun 11, 2018

My understanding is we're at a weird middle ground because I didn't know CoreFX had it disabled: CoreCLR uses it, but CoreFX doesn't.

We should be able to disable it in CoreCLR as well and remove it again, with the perf cost stephentoub mentioned. (I don't know the build arg to do this.) If it's ok to have it as a prebuilt, we could enable it for CoreFX so that we're at least using what we already have.

@jkotas
Copy link
Member

jkotas commented Jun 11, 2018

The performance cost to disable it in CoreCLR is prohibitive. It will cause performance regressions that are not going to be acceptable. (Unless we pick up the compiler with SkipLocalsInitAttribute and start using this feature.)

@dagood
Copy link
Member

dagood commented Jun 11, 2018

[@erozenfeld] @sbomer and I have been building ILLink.Tasks from source (including Cecil) and publishing the packages. We can help with integrating that into source-build if that is what is required.

Unless there are alternative ways to avoid the perf impact, that is what we need to do to get rid of the prebuilt dependency, yeah. Thanks for the offer. Here's a doc on the basics of the source-build repo if you want to see the general expectations ahead of time--it doesn't seem to me like we have bandwidth to get that in our imminent releases though: https://github.com/dotnet/source-build/blob/master/Documentation/2.1-update-process.md.

/cc @dleeapho

[@erozenfeld] Is source build not allowed to use any packages?

Check out https://github.com/dotnet/source-build#goals for why we don't want prebuilt (downloaded) dependencies in source-build. This guideline in particular: https://fedoraproject.org/wiki/Packaging:Guidelines#No_inclusion_of_pre-built_binaries_or_libraries. The "area-prebuilt-reduction" label tracks exceptions we're aiming to get rid of.

[@stephentoub] I know I've had cases in recent memory where things got trimmed away, so I'm not sure what's going on, maybe it's a very recent change? Or... maybe that's just for source build?

Yep, just source-build. /p:ILLinkTrimAssembly=false is set when building CoreFX from source.

@tmds
Copy link
Member

tmds commented Jun 12, 2018

it doesn't seem to me like we have bandwidth to get that in our imminent releases

By what release could we change this? 2.1.2?

@erozenfeld
Copy link
Member

@dagood Is this guideline about what is included in the resulting binaries or about everything used during the build?
https://fedoraproject.org/wiki/Packaging:Guidelines#No_inclusion_of_pre-built_binaries_or_libraries
ILLink.Tasks is not included in the output, it's only used during the build. Are all other tools (e.g., c++ and c# compilers and linkers) used during source-build built from source?

@erozenfeld
Copy link
Member

@jkotas We can bring back your workaround in the runtime to ignore initlocals in SPC if the linker has to be disabled... We'll still have regressions in corefx assemblies.

@tmds
Copy link
Member

tmds commented Jun 12, 2018

Are all other tools (e.g., c++ and c# compilers and linkers) used during source-build built from source

@erozenfeld For the native toolchain, this is the case (since that comes from the OS packages, which meet source-build requirements). For the C# compiler, this is not yet the case. For this reason, the .NET Core packages are not shipping as part of the Fedora regular repositories (since we don't meet the guideline).

To solve this, we need to either use a compiler from the previous release (since that was source-build), or we need to do a two-stage build. From the doc:

You may bootstrap this build with a "bootstrap" pre-built binary, but after this is complete, you must immediately increment Release, drop the "bootstrap" pre-built binary, and build completely from source.

@tmds
Copy link
Member

tmds commented Jun 22, 2018

@erozenfeld which of the options mentioned so far are feasible to do as part of a 2.1 service release?

@dagood
Copy link
Member

dagood commented Jun 22, 2018

For either of those we'd first have to start building ILLink.Tasks from source, and for N-1 my understanding is it would have to be persisted from one release to the next--I don't think we have a mechanism for this, since it isn't part of the SDK.

For scheduling, I think that's more on us in source-build since I don't think anyone's been able to add a repo yet without deep repo knowledge. @dleeapho ?

@tmds
Copy link
Member

tmds commented Aug 29, 2018

@dleeapho can you please look into this?

@dleeapho dleeapho added the area-product-experience Improvements in the end-user's product experience label Aug 29, 2018
@dleeapho
Copy link
Contributor

Per our discussion offline, @dagood can you investigate how we can get this in for 2.1.x?

@dagood
Copy link
Member

dagood commented Aug 29, 2018

Will do, I put it at the top of my backlog.

@dagood
Copy link
Member

dagood commented Sep 7, 2018

I had some time to look at this and got it building and consumed by CoreCLR, but the task makes the MSBuild node exit:

4>ILLinkTrimAssembly:
    Creating directory "/work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/PreTrim/".
    Moving file from "/work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/System.Private.CoreLib.dll" to "/work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/PreTrim/System.Private.CoreLib.dll".
    Moving file from "/work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/System.Private.CoreLib.pdb" to "/work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/PreTrim/System.Private.CoreLib.pdb".
    illink -d /work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/PreTrim -out /work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/ -s ILLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep -m ClearInitLocalsAssemblies System.Private.CoreLib -r System.Private.CoreLib -c skip -u skip -p link System.Private.CoreLib -b true -v true --strip-resources false -h LdtokenTypeMethods,InstanceConstructors
0>MSBUILD : error MSB4166: Child node "2" exited prematurely. Shutting down. Diagnostic information may be found in files in "/tmp/" and will be named MSBuild_*.failure.txt. This location can be changed by setting the MSBUILDDEBUGPATH environment variable to a different directory.
3>/work/packages/microsoft.netcore.compilers/2.8.0-beta2-62719-08/tools/Microsoft.CSharp.Core.targets(52,5): warning MSB5021: Terminating the task executable "dotnet" and its child processes because the build was canceled. [/work/src/coreclr/src/ToolBox/SOS/NETCore/SOS.NETCore.csproj]

/tmp doesn't have the promised MSBuild_*.failure.txt after the build terminates.

I'm using Docker image microsoft/dotnet-buildtools-prereqs:centos-7-b46d863-20180719033416 and building ./build.sh /p:RootRepo=corefx using dade47c.

@erozenfeld @sbomer, do you have any suggestions on figuring out what's going wrong? Even better, could you look into this? (Should be easy to repro.)


Adding this repo didn't bring in any new prebuilts that look like an issue. It looks like they just need to get on the right versions to use source-built stuff:

14 new packages used not in baseline!
Microsoft.NETCore.App.2.0.0-beta-001509-00
Microsoft.NETCore.Platforms.2.0.0-beta-25006-01
NETStandard.Library.2.0.0-beta-25006-01
Newtonsoft.Json.9.0.1
NuGet.Common.4.3.0-preview1-2500
NuGet.Configuration.4.3.0-preview1-2500
NuGet.DependencyResolver.Core.4.3.0-preview1-2500
NuGet.Frameworks.4.3.0-preview1-2500
NuGet.LibraryModel.4.3.0-preview1-2500
NuGet.Packaging.4.3.0-preview1-2500
NuGet.Packaging.Core.4.3.0-preview1-2500
NuGet.ProjectModel.4.3.0-preview1-2500
NuGet.Protocol.4.3.0-preview1-2500
NuGet.Versioning.4.3.0-preview1-2500

@sbomer
Copy link
Member

sbomer commented Sep 8, 2018

@dagood very weird, not sure what that error is.
That commit doesn't exist when I clone. Did you delete the branch it was on (and if so, could you push it back)?

@dagood
Copy link
Member

dagood commented Sep 10, 2018

Ah, sorry, it's on my fork, forgot the commit screen doesn't mention that. https://github.com/dagood/source-build/tree/add-illink/2.1

@dagood
Copy link
Member

dagood commented Sep 10, 2018

The pseudo-command CoreCLR runs is this:

illink -d /work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/PreTrim -out /work/src/coreclr/bin/obj/Linux.x64.Release/System.Private.CoreLib/ -s ILLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep -m ClearInitLocalsAssemblies System.Private.CoreLib --verbose -r System.Private.CoreLib -c skip -u skip -p link System.Private.CoreLib -b true -v true --strip-resources false -h LdtokenTypeMethods,InstanceConstructors

I decompiled illink.dll from the package CoreCLR uses in official builds (https://dotnet.myget.org/feed/dotnet-buildtools/package/nuget/ILLink.Tasks/0.1.5-preview-1461378) vs. the source we're building, and I see this in the diff (among other changes):

--- "a/.\\sb\\proj\\Mono.Linker\\Driver.cs"
+++ "b/.\\official\\proj\\Mono.Linker\\Driver.cs"
@@ -66,7 +66,6 @@ namespace Mono.Linker
 			Console.WriteLine("   -g                  Generate a new unique guid for each linked module (true or false)");
-			Console.WriteLine("   -v                  Keep members needed by debugger (true or false)");
+			Console.WriteLine("   -v                  Keep memebers needed by debugger attributes (true or false)");
+			Console.WriteLine("   -h                  List of reflection heuristics separated with a comma.");
+			Console.WriteLine("                       Supported heuristics:");
+			Console.WriteLine("                         LdtokenTypeMethods:   mark all methods of types whose token is used");
+			Console.WriteLine("                                               in an ldtoken instruction");
+			Console.WriteLine("                         LdtokenTypeFields:    mark all fields of types whose token is used");
+			Console.WriteLine("                                               in an ldtoken instruction");
+			Console.WriteLine("                         InstanceConstructors: mark all instance constructors in types");
+			Console.WriteLine("                                               where an instance member has been marked but");
+			Console.WriteLine("                                               none of the instance constructors have been marked");
 			Console.WriteLine("   -l                  List of i18n assemblies to copy to the output directory");
 			Console.WriteLine("                         separated with a comma: none,all,cjk,mideast,other,rare,west");

The Console.WriteLine might not be making it to any logs and the Environment.Exit(1) in the Usage method could be doing the early exit. https://github.com/mono/linker/blob/c85962b3aa514ff23161f0b5a1ef16fa89b9e844/linker/Linker/Driver.cs#L412

I did a search and found this closed PR: dotnet/linker#60. I'm guessing the version of ILLink.Tasks used by CoreCLR official builds isn't the same as the linker repo's master? How should we rectify this?

@dagood
Copy link
Member

dagood commented Sep 10, 2018

I read through the PR (my bad) and saw this:

Since you are pushing back on adding these optional heuristics to the core linker, we'll keep them in our version of the linker for now. I'll close this PR and open another one to merge just MarkStep changes to allow the needed extension points.

@erozenfeld, where is the other version, so we can include it in source-build?

@dagood
Copy link
Member

dagood commented Sep 17, 2018

Created PR #778 to add the linker repo with a patch to add the -h feature. Patch removal tracked by #777.

The builds of ILLink.Tasks currently come from a non-public repo (@sbomer and @erozenfeld helped me find this, thanks!) and I was able to make a patch for the feature we need. I expect the patch not to require much maintenance: there are only a handful of ILLink.Tasks package builds total. However, if it becomes a problem, we will start a dotnet/linker fork of mono/linker where the changes will be maintained.

The internal repo doesn't have any other notable changes: just small things to support the signed Microsoft build infrastructure. If we make the fork, I expect those changes would be made public without any problems, to make sure maintenance can happen in just one place.

@markwilkie markwilkie added this to the S142 Sept 24 - Oct 12 (9/24/2018) milestone Sep 26, 2018
@dagood
Copy link
Member

dagood commented Oct 31, 2018

Closing as resolved: the linker repo is in the build and the change has flowed through all branches.

@dagood dagood closed this as completed Oct 31, 2018
@tmds
Copy link
Member

tmds commented Oct 31, 2018

Thank you @dagood!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-prebuilts Reducing the number of prebuilt packages in the tarball area-product-experience Improvements in the end-user's product experience
Projects
None yet
Development

No branches or pull requests