dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.47k stars 4.76k forks source link

Trim embedded resource #96442

Open tranb3r opened 11 months ago

tranb3r commented 11 months ago

Description

The dotnet trimmer does not seem to trim an embedded resource that is not used. Is there a way to force the trimmer to remove embedded resources when they are not used by the application?

Reproduction Steps

  1. Create a console application.
  2. Add an EmbeddedResource.
  3. Publish the application with trimming enabled.
  4. Inspect the published assembly.

Expected behavior

The embedded resource should be removed from the assembly, since the application is not using it.

Actual behavior

The embedded resource is still here, even if it's not used by the application.

Regression?

No response

Known Workarounds

No response

Configuration

.net8

Other information

No response

huoyaoyuan commented 11 months ago

How to determine if a resource is used?

For code, most code elements are used by direct references. They can be precisely analysed. For embedded resources, it's quite common to concatenate their names, which is not analysable in reflection.

tranb3r commented 11 months ago

Embedded resources can be big. It would great to have a way to remove them. I understand it's difficult to do determine if a resource is used. It's also difficult to determine if some code is used. For example, if some code is only used via reflection, it's removed by the trimmer, and this is very similar the behavior I'd like to have regarding embedded resources. So, it could be the default behavior to remove embedded resources, and have some attribute to let the code indicate where it's using an embedded resource that should not be removed. Just an idea...

ghost commented 11 months ago

Tagging subscribers to this area: @agocke, @sbomer, @vitek-karas See info in area-owners.md if you want to be subscribed.

Issue Details
### Description The dotnet trimmer does not seem to trim an embedded resource that is not used. Is there a way to force the trimmer to remove embedded resources when they are not used by the application? ### Reproduction Steps 1. Create a console application. 2. Add an EmbeddedResource. 3. Publish the application with trimming enabled. 4. Inspect the published assembly. ### Expected behavior The embedded resource should be removed from the assembly, since the application is not using it. ### Actual behavior The embedded resource is still here, even if it's not used by the application. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration .net8 ### Other information _No response_
Author: tranb3r
Assignees: -
Labels: `untriaged`, `area-Tools-ILLink`
Milestone: -
vitek-karas commented 11 months ago

The correct solution would have to be very similar to what we do for reflection:

There would still be possible issues - what if I have a helper method which takes the name of the resource to access - no way to annotate that (even if the method is called with a constant string). And so on.

Definitely solvable - after all it's basically very similar to what we solved for reflection APIs. But non-trivial. I think we would need a good reason to invest into this.

Another potential improvement in this area would be the ability to track string resources (typically exception messages) and selectively remove those - after all, why would I need to keep the exception message for exception which is never thrown by my application. This is probably even more complicated unfortunately.

We have some knobs in this area:

tranb3r commented 11 months ago

I've just tested the removal of several embedded resources using a substitution XML and it works perfectly. My android apk size has decreased by ~500kB. This is exactly what I was looking for :) Thanks a lot!

vitek-karas commented 11 months ago

I'm glad it works for you, just note that you're in "Semi-unsupported" territory - we may break you couple of years from now :-)