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

Reduce size of PublishSingleFile binary #12629

Closed
ghost opened this issue May 5, 2019 · 41 comments
Closed

Reduce size of PublishSingleFile binary #12629

ghost opened this issue May 5, 2019 · 41 comments
Assignees
Milestone

Comments

@ghost
Copy link

ghost commented May 5, 2019

With C++ you can make a single file executable:

$ cat aaaaa.cpp
#include <iostream>
int main() {
   std::cout << "bbbbb ccccc" << std::endl;
}

$ x86_64-w64-mingw32-g++ -s -static -std=c++14 -o aaaaa.exe aaaaa.cpp
$ ./aaaaa.exe
bbbbb ccccc

with a decent size:

$ wc -c aaaaa.exe
868864 aaaaa.exe

with C# you can make a single file executable:

$ dotnet new console -o aaaaa
$ dotnet publish -r win-x64 /p:PublishSingleFile=true aaaaa
$ cd aaaaa/bin/Debug/netcoreapp3.0/win-x64/publish
$ ./aaaaa.exe
Hello World!

but the size is 80 times larger:

$ wc -c aaaaa.exe
70272264 aaaaa.exe

it seems that DLLs are being loaded that dont need to be. Using these commands:

cd aaaaa/bin/Debug/netcoreapp3.0/win-x64
ldd aaaaa.exe |
awk '{print $1}' |
while read each
do
   if [ -f "$each" ]
   then
      echo "$each"
   fi
done |
xargs wc -c aaaaa.exe

Result:

 337408 aaaaa.exe
  18696 api-ms-win-core-file-l1-2-0.dll
  18696 api-ms-win-core-file-l2-1-0.dll
  21256 api-ms-win-core-localization-l1-2-0.dll
  19208 api-ms-win-core-processthreads-l1-1-1.dll
  19208 api-ms-win-core-synch-l1-2-0.dll
  19208 api-ms-win-core-timezone-l1-1-0.dll
  22792 api-ms-win-crt-convert-l1-1-0.dll
  20744 api-ms-win-crt-filesystem-l1-1-0.dll
  19720 api-ms-win-crt-heap-l1-1-0.dll
  19208 api-ms-win-crt-locale-l1-1-0.dll
  27912 api-ms-win-crt-math-l1-1-0.dll
  23304 api-ms-win-crt-runtime-l1-1-0.dll
  24840 api-ms-win-crt-stdio-l1-1-0.dll
  24840 api-ms-win-crt-string-l1-1-0.dll
  21256 api-ms-win-crt-time-l1-1-0.dll
1016584 ucrtbase.DLL
1674880 total

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?

@AaronRobinsonMSFT
Copy link
Member

@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 api-ms-win-crt-stdio-l1-1-0.dll is most definitely going to be needed if like the C++ example a string is being written to stdout. The other aspect of this is the ability for the single binary to be run on Windows version that don't have the necessary API sets (e.g. Windows 7). Basically those files are definitely needed by the VM in most scenarios.

@ghost
Copy link
Author

ghost commented May 5, 2019

@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?

@AaronRobinsonMSFT
Copy link
Member

@cup Ah. Sorry about that, I see the ldd command now. Sorry for the confusion, but the response is generally the same. The VM doesn't know what the application is going to do or on which Windows platform it may be executed on. I agree that in this example it would be generally simple to reduce the set, but this is the trivial case. However, what about applications that consume plug-ins or if additional diagnostic knobs (e.g. ComPlus_*) are set for debugging a crash in the future?

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.

cc @swaroop-sridhar @jeffschwMSFT

@AaronRobinsonMSFT AaronRobinsonMSFT changed the title PublishSingleFile size Reduce size of PublishSingleFile binary May 5, 2019
@ghost
Copy link
Author

ghost commented May 5, 2019

@AaronRobinsonMSFT why would we need to "ask the developer" anything?

with C and C++, you just compile with -static and any needed libraries are
statically linked at compile time.

is something like that orthogonal to the C# build system? does .NET Core really
have no way to detect what libraries are actually used in a program and link
only those?

@AaronRobinsonMSFT
Copy link
Member

AaronRobinsonMSFT commented May 5, 2019

@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.

@vitek-karas
Copy link
Member

Just add --self-contained false. I get 335KB for a console hello world.

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 --self-contained false the app is built as framework-dependent. It means it requires the runtime and the framework to be installed on the machine. On the other hand it can be really small.

@tomrus88
Copy link

tomrus88 commented May 5, 2019

@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...

@vitek-karas
Copy link
Member

@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.

@svick
Copy link
Contributor

svick commented May 5, 2019

@AaronRobinsonMSFT

The VM doesn't know what the application is going to do or on which Windows platform it may be executed on.

It can know that, if I specify RID of e.g. win10-x64 during publish. I was surprised that the size of a self-contained single-file binary for win-x64 is exactly the same as for win10-x64. Isn't that something that could be improved?

@AaronRobinsonMSFT
Copy link
Member

Isn't that something that could be improved?

@svick Absolutely it can be improved. I didn't realize we have that specific of a RID. If the option exists to specify win or win10 then we could definitely reduce that scenario much easier - good catch.

A real fix would be something like C or C++ where only the used libraries are
statically linked, perhap automatically or with switch like -lhostfxr.

@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.

@tomrus88
Copy link

tomrus88 commented May 5, 2019

@AaronRobinsonMSFT I was unable to use ILLink.Task as well, but got completely different errors.

f:\Dev\testapp>dotnet --version
3.0.100-preview4-011223
dotnet new console -o testapp
cd testapp
dotnet new nuget
edit nuget.config as described in docs
dotnet add package ILLink.Tasks -v 0.1.6-prerelease.19253.1
dotnet publish -c release -r win-x64 -o out

Got following errors

C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018: The "ILLink" task failed unexpectedly. [f:\Dev\testapp\testapp.csproj]
C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018: System.NullReferenceException: Object reference not set to an instance of an object. [f:\Dev\testapp\testapp.csproj]
C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018:    at ILLink.Tasks.ILLink.GenerateCommandLineCommands() [f:\Dev\testapp\testapp.csproj]
C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018:    at Microsoft.Build.Utilities.ToolTask.Execute() [f:\Dev\testapp\testapp.csproj]
C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() [f:\Dev\testapp\testapp.csproj]
C:\Users\TOM_RUS\.nuget\packages\illink.tasks\0.1.6-prerelease.19253.1\build\ILLink.Tasks.targets(247,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask) [f:\Dev\testapp\testapp.csproj]

@AaronRobinsonMSFT
Copy link
Member

@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 /bl to the build command and examine the .binlog for exactly what is failing. It is possible the error is simple or could be a blocking issue for consuming those targets for 3.0. External support and integration is something that is being considered for the 3.0 timeframe though.

@Symbai
Copy link

Symbai commented May 5, 2019

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.

@jeffschwMSFT
Copy link
Member

cc @swaroop-sridhar

@swaroop-sridhar
Copy link
Contributor

@cup @Symbai @tomrus88

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:

dotnet publish -r <rid> /p:PublishTrimmed=true /p:PublishSingleFile=true

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.

@tomrus88
Copy link

tomrus88 commented May 9, 2019

@swaroop-sridhar I've tried daily build of .net core and got following results using single file publish:
Console App 68.4 MB without trimming, 28.2 MB with trimming
WinForms App 136 MB without trimming, 51.8 MB with trimming
WPF App 136 MB without trimming, fails to publish with trimming, build log attached
msbuild.zip
image

@jeffschwMSFT
Copy link
Member

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.

@tomrus88
Copy link

tomrus88 commented May 24, 2019

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.

@sbomer
Copy link
Member

sbomer commented May 24, 2019

@tomrus88 thank you for letting us know - I'm taking a look now. What is the failure you're seeing?

@tomrus88
Copy link

@tomrus88 thank you for letting us know - I'm taking a look now. What is the failure you're seeing?

Looks like you already found out what's wrong :)

@tomrus88
Copy link

tomrus88 commented May 28, 2019

So now trimming works again, and there's latest results based on 3.0.100-preview6-012099 daily build:
Console App 67.7 MB without trimming (got smaller), 32.3 MB with trimming (got bigger)
WinForms App 165 MB without trimming (got bigger), 65.0 MB with trimming (got bigger)
WPF App 165 MB without trimming (got bigger), 65.0 MB with trimming

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:
mscordaccore.dll = mscordaccore_amd64_amd64_4.6.27724.71.dll
sos.dll = sos_amd64_amd64_4.6.27724.71.dll

@sbomer
Copy link
Member

sbomer commented May 28, 2019

@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?

@tomrus88
Copy link

tomrus88 commented May 28, 2019

Could you try doing a clean build?

@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:
dotnet publish -c Release -r win-x64
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true
dotnet publish -c Release -r win-x64 /p:PublishTrimmed=true /p:PublishSingleFile=true

And outputs:
publish_nosinglefile.zip
publish_singlefile.zip
publish_singlefiletrim.zip

@swaroop-sridhar
Copy link
Contributor

@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.

@tomrus88
Copy link

tomrus88 commented May 29, 2019

I've noticed even bigger issue with PublishTrimmed option, the WinForms and WPF apps crashing due to missing dll's.

Application: wfcore.exe
CoreCLR Version: 4.6.27724.71
.NET Core Version: 3.0.0-preview6-27727-02
Description: The process was terminated due to an unhandled exception.
Exception Info: System.TypeLoadException: Could not load type 'System.ComponentModel.Component' from assembly 'System.Windows.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
   at wfcore.Program.Main()
Application: wpfcoreapp.exe
CoreCLR Version: 4.6.27728.71
.NET Core Version: 3.0.0-preview6-27728-04
Description: The process was terminated due to an unhandled exception.
Exception Info: System.TypeLoadException: Could not load type 'System.Windows.Markup.IQueryAmbient' from assembly 'System.Threading.Thread, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

Update: Tested again on SDK 3.0.100-preview6-012113
Console App 67.5 MB without trimming, 27.2 MB with trimming
WinForms App 164 MB without trimming, 51.0 MB with trimming
WPF App 164 MB without trimming, 65.2 MB with trimming
and WinForms trimmed app is running fine again, WPF trimmed app still crashes, but now with different error

Application: wpfcoreapp.exe
CoreCLR Version: 4.6.27728.71
.NET Core Version: 3.0.0-preview6-27728-04
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Windows.Markup.XamlParseException: The method or operation is not implemented. ---> System.NotImplementedException: The method or operation is not implemented.
   at System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlType(BamlType bamlType, Int16 typeId)
   at System.Windows.Baml2006.Baml2006SchemaContext.GetXamlType(Int16 typeId)
   at System.Windows.Baml2006.Baml2006Reader.Process_ElementStart()
   at System.Windows.Baml2006.Baml2006Reader.Process_OneBamlRecord()
   at System.Windows.Baml2006.Baml2006Reader.Process_BamlRecords()
   at System.Windows.Baml2006.Baml2006Reader.Read()
   at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   --- End of inner exception stack trace ---
   at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)
   at System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean bSkipJournaledProperties)
   at System.Windows.Application.DoStartup()
   at System.Windows.Application.<.ctor>b__1_0(Object unused)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at wpfcoreapp.App.Main()

@mikem8361
Copy link
Member

mikem8361 commented May 29, 2019 via email

@tomrus88
Copy link

@sbomer @swaroop-sridhar I've made a separate issue about WPF app crashing with ILLink dotnet/linker#595

@tomrus88
Copy link

tomrus88 commented Jun 5, 2019

File size information for .NET Core SDK 3.0.100-preview7-012261

Project Type Self Contained SingleFile SingleFile+Trim
Console 69MB 69MB 28.4MB
WinForms 152MB 168MB 101MB
WPF 152MB 168MB 101MB

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?).
Trimmed size for WinForms and WPF increased significantly with slight decrease for Console projects. Trimmed WPF single file apps no longer crashing.

@jeffschwMSFT
Copy link
Member

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.

@forestbat
Copy link

@jeffschwMSFT 101MB is still too big,do you have further solution?

@jeffschwMSFT
Copy link
Member

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.

@sbomer
Copy link
Member

sbomer commented Jun 5, 2019

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.

@swaroop-sridhar
Copy link
Contributor

we believe the build targets are passing in additional files to bundle

This bug is tracked in dotnet/sdk#3257

@swaroop-sridhar
Copy link
Contributor

swaroop-sridhar commented Jun 12, 2019

dotnet/sdk#3257 is now fixed.

The other issues for reducing size are:

So, I think we can close this issue.

@swaroop-sridhar
Copy link
Contributor

@cup: I've referenced the SOS issue above.
@sven: If there are further issues about enabling Linker features more aggressively, please link them to this issue.

I've closed the issue now, since none of the work remaining is in CoreCLR repo.

@tomrus88
Copy link

tomrus88 commented Jun 13, 2019

@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?

@swaroop-sridhar
Copy link
Contributor

swaroop-sridhar commented Jun 13, 2019

@tomrus88 the fix for dotnet/sdk#3257 isn't available in that build.
I've verified that the fix works in the SDK branch, it'll propagate to the core-sdk today/tomorrow.

@tomrus88
Copy link

tomrus88 commented Jun 14, 2019

Single file size statistics for .NET Core SDK 3.0.100-preview7-012403

Project Type Self Contained Single File Single File+Trim
Console 67.4MB 67.4MB 27MB
WinForms 151MB 151MB 86.9MB
WPF 151MB 151MB 86.9MB

So double write bug appears to be fixed in latest daily preview build and file size is slightly lower now.

@ghost
Copy link
Author

ghost commented Nov 17, 2019

Another option is Roslyn:

C:\microsoft.net.compilers.3.3.1> type sun-mon.cs
using System;
class Program {
   static void Main() {
      Console.WriteLine("sunday monday");
   }
}

C:\microsoft.net.compilers.3.3.1> tools\csc.exe sun-mon.cs
C:\microsoft.net.compilers.3.3.1> sun-mon.exe
sunday monday

C:\microsoft.net.compilers.3.3.1> dir sun-mon.exe
2019-11-16  11:34 PM             3,584 sun-mon.exe

https://nuget.org/packages/Microsoft.Net.Compilers

@vitek-karas
Copy link
Member

@cup The .exe produced by the C# compiler (Roslyn) is not the "self-contained" app and it's not a .NET Core executable. It needs a CLR runtime and framework to work. Which one that will be is determined on how you run it. If you just run it as is on Windows, it will run on .NET Framework (the desktop version which is part of Windows OS). You can try this by changing the code to be something like this:

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:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscorlib.dll

It's actually not possible to run the .exe as is with .NET Core as required configuration files are missing. You could add a file sun-mon.runtimeconfig.json next to it with content like this:

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "3.0.0"
    }
  }
}

Then running it via the dotnet.exe will look like this:

dotnet sun-mon.exe
C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0\System.Private.CoreLib.dll

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.

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@Herz3h
Copy link

Herz3h commented Sep 7, 2020

In my case, if I create zip folder with executable + dll: 29MB
If I use PublishSingleFile and PublishTrimmed: 129MB

It still is too big. Using .net core 3.1 app on windows.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests