-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Reduce size of PublishSingleFile binary #12629
Comments
@cup What about the DLLs mentioned above indicate they aren't needed? Those API sets are native dependencies for the VM itself and have nothing to do with the managed application. The |
@AaronRobinsonMSFT it seems you wholly misunderstood my post. the DLLs i listed are ones that are required, as you said. its the other 200 or so that arent, or so it would appear. so to repeat, is there a way to only included needed DLLs in the executable? |
@cup Ah. Sorry about that, I see the This isn't to say the developer can't declare "trust me, these are all the binaries I will need", but that would require a rather large leap of faith for anyone, even one of the runtime developers, to be confident the VM isn't going to need one of them in some future scenario. The issue about size for single-exe is definitely a concern and reducing that is something we are working on. I am just unsure if asking the developer to provide a list of what they believe are needed is a path for success in anything more complicated than a "hello world" example. |
@AaronRobinsonMSFT why would we need to "ask the developer" anything? with C and C++, you just compile with is something like that orthogonal to the C# build system? does .NET Core really |
@cup Are we talking about native libraries or managed libraries here? For managed libraries there is definitely a way to reduce the size. Details about the tooling can be found at https://github.com/dotnet/core/blob/master/samples/linker-instructions.md. This is apart of the work I referred to above. For native libraries it is a bit more complicated. In particular on Windows one of the reasons has to do with downlevel support through API-sets as well as delay loading of other binaries that may or may not be needed. The thought being there is no reason to sacrifice process memory if the binary is never used so it may be delay loaded to reduce the runtime memory footprint. |
Just add Currently the default for publish (carryover from 2.* days) is to create self-contained applications. This means the entire runtime and all of the framework is included in the app. If you use |
@vitek-karas isn't whole point of single file distribution is that it doesn't have any external dependencies? Be it runtime, framework or any other dependency... |
@tomrus88 one of the use cases for single-file is definitely the "no dependency" distribution you mention. In that case, as of now .NET Core doesn't have a solution which would provide "small" package size. Projects like ILLinker should help, right now though the size improvements it offers are nowhere near good enough to make the apps comparable in size to the C++ sample above. There are other use cases though. One such case is where it's OK to require globally installed runtime, but the desire is to have the application itself as a single executable. For example for ease of deployment. In these cases the above mentioned setting can get the application size to really small numbers. |
It can know that, if I specify RID of e.g. |
@svick Absolutely it can be improved. I didn't realize we have that specific of a RID. If the option exists to specify
@cup That is what the self contained basically provides to you in a final binary - except there is no link time code gen that can reduce the native footprint due to all the issues I have mentioned above. A managed solution does exist - https://github.com/dotnet/core/blob/master/samples/linker-instructions.md. As far as making the managed linker just work that is definitely what we are working toward. However. as I mentioned above the native solution is not as simple as is assumed here for all the reasons I have previously mentioned. |
@AaronRobinsonMSFT I was unable to use ILLink.Task as well, but got completely different errors.
Got following errors
|
@cup I am not an owner nor contributor to the ILLink tool. Both the coreclr and corefx repos consume ILLink and we use it to reduce assembly footprint in various scenarios. The instructions aside, I was pointing out the existence of a tool that does what is being requested but only for managed assemblies. It is also the tool we will be using longer term to address the size issue in single file scenarios with respect to managed assemblies. @cup and @tomrus88 If you are hitting issues there is a feedback section to request help. Based on the documentation in those instructions it appears they are for 2.0 at present so probably need to be updated. Definitely worth filing an issue on that. I would suggest adding a |
Removing unnecessary dlls from self contained applications is much needed. Without single file it throws more than 250(!) dlls in the output directory which is a mess. The mono linker isn't working most if the time especially with WPF or Winforms applications and last time I've checked it didn't even worked for .NET Core 3 at all. I think there should be a native / inbuilt solution that self contained only copies the required dlls. It should work like all the native compilers. Copying the whole framework was acceptable for .NET Core 2 and previous where applications were meant to be server applications. Now that .NET Core 3 also supports end user desktop applications you cannot share a folder with over 250 files or binaries with over 70mb where the actual application code is less than 50 lines of code. |
In the upcoming Preview 6, we plan to integrate the ILLinker into the .NET core SDK. Once this is ready, you'll be able to use the linker and single-exe options seamlessly, as in:
This will generate a self-contained executable for the app, with unnecessary native and managed DLLs removed. There are things we can do to further reduce the binary size, but I think this will largely address the concerns you've raised above. @sbomer can you please provide the file-count and single-file size for HelloWorld app when using the linker with native-file trimming? Thanks. |
@swaroop-sridhar I've tried daily build of .net core and got following results using single file publish: |
Thanks @tomrus88 for giving the mono/linker a try and publishing the sizes. The gap with WPF is an issue that we are tracking. One potential cause of the issue is that we loose the assembly roots defined in xaml, there are others. We hope to have changes to have this work more often in an upcoming preview. |
PublishTrimmed option now failing on all project types (Console/WinForms/WPF) as of latest daily .NET Core build (I have 3.0.100-preview6-012077 installed atm). Probably has something to do with this dotnet/linker#567 being merged. |
@tomrus88 thank you for letting us know - I'm taking a look now. What is the failure you're seeing? |
Left-over from https://github.com/mono/linker/pull/567/files. I believe this is what's causing https://github.com/dotnet/coreclr/issues/24397#issuecomment-495720076.
Looks like you already found out what's wrong :) |
Left-over from https://github.com/mono/linker/pull/567/files. I believe this is what's causing https://github.com/dotnet/coreclr/issues/24397#issuecomment-495720076.
So now trimming works again, and there's latest results based on 3.0.100-preview6-012099 daily build: I also find it interesting, that without using single file publish, WinForms App and WPF App is only 149MB, where does those extra 16MB come from? Also there's 2 pairs of identical files in publish folder when not using single file publish, not sure why we need those: |
@tomrus88 I appreciate the interest and the numbers you've shared, thanks! The numbers for trimming are different because we've been changing the default settings to be more conservative (which will make it tend to work better for apps/frameworks that use reflection - like WPF, but won't be able to remove as much code). About the extra 16MB: Your original numbers are closer to what I've been seeing. I can't tell without looking at your publish output, but I've noticed that sometimes extra files from my project get included when I do a publish. Could you try doing a clean build? My understanding is that sos may be removed from the output soon - @mikem8361, could you address this? |
@sbomer Doing clean build doesn't seems to change anything, still getting same 165MB single file, 65MB single file trimmed and ~150MB without single file for WinForms project. Commands I used to publish: And outputs: |
@tomrus88 thanks for pointing out the issue of file size disparity with single-file. This is certainly unexpected, and wasn't the case when using the Preview5 release of dotnet SDK. I'll investigate further. Thanks. |
I've noticed even bigger issue with PublishTrimmed option, the WinForms and WPF apps crashing due to missing dll's.
Update: Tested again on SDK 3.0.100-preview6-012113
|
I don’t have an exact date but I hope that SOS in coreclr will be removed before Preview 7 towards the next of month.
|
@sbomer @swaroop-sridhar I've made a separate issue about WPF app crashing with ILLink dotnet/linker#595 |
File size information for .NET Core SDK 3.0.100-preview7-012261
Bug where single file publish for WinForms/WPF has 16MB (168-152) extra compared to no single file still exist (somehow Console not affected by this bug?). |
Thanks @tomrus88 for the set of numbers. I chatted with @swaroop-sridhar this week about the additional content in the bundle, and we believe the build targets are passing in additional files to bundle. We are looking deeper and will have an update. Happy to hear that WPF trimmed is working as expected. |
@jeffschwMSFT 101MB is still too big,do you have further solution? |
Keep in mind that this number has ~15 mb of things that should not be part of it, which we hope to get removed. Starting in Preview6 the linker will be integrated and the full breadth of options for shrinking will be available. Depending on your scenario you can the app down in the 70mb range - but like any linker technology developer intervention will be necessary in order to ensure the app continues to work. |
Echoing @jeffschwMSFT: there will be ways for you to do more manual work to further reduce the size, but it won't be easy... it will essentially involve telling the linker about all roots needed by reflection and native code. We'll have updated docs on this in the next preview. |
This bug is tracked in dotnet/sdk#3257 |
dotnet/sdk#3257 is now fixed. The other issues for reducing size are:
So, I think we can close this issue. |
@swaroop-sridhar Is fix for dotnet/sdk#3257 available in daily .NET Core SDK builds? Because i'm still getting those extra 15MB on latest .NET Core SDK 3.0.100-preview7-012386. Or was this fix for some different bug? |
@tomrus88 the fix for dotnet/sdk#3257 isn't available in that build. |
Single file size statistics for .NET Core SDK 3.0.100-preview7-012403
So double write bug appears to be fixed in latest daily preview build and file size is slightly lower now. |
Another option is Roslyn:
|
@cup The using System;
class Program {
static void Main() {
Console.WriteLine(typeof(object).Assembly.Location);
}
} Then compile it with the C# compiler and run the exe. It will print out something like:
It's actually not possible to run the {
"runtimeOptions": {
"tfm": "netcoreapp3.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "3.0.0"
}
}
} Then running it via the
So now it did run against .NET Core (3.0 in this case). Note that it used the runtime and framework installed in program files to do so. |
In my case, if I create zip folder with executable + dll: 29MB It still is too big. Using .net core 3.1 app on windows. |
With C++ you can make a single file executable:
with a decent size:
with C# you can make a single file executable:
but the size is 80 times larger:
it seems that DLLs are being loaded that dont need to be. Using these commands:
Result:
So if we only use required DLL the size is 40 times smaller. Does
dotnet publish have a way to "strip" the executable, or only include needed
DLL?
The text was updated successfully, but these errors were encountered: