-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Marking libraries as IsTrimmable #24238
Comments
Thank you for your feedback. Tagging and routing to team members for discussion and consideration. |
//cc: @AlexGhiondea, @weshaggard, @maririos |
If possible assemblies should be marked as trimmable only once all of the trimmer related warnings are resolved in them. Currently the only way to get all of the warnings is to use the library in an app and trim that app - the setup is described here https://docs.microsoft.com/en-us/dotnet/core/deploying/prepare-libraries-for-trimming#show-all-warnings. |
Most new libraries have a limited amount of reflection in them. There is some in the core but we can annotate it appropriately. What worries me more is how do we test libraries and ensure that trimmed versions are functional. @vitek-karas @MichalStrehovsky what testing strategies do you employ for BCL libraries? |
We mostly rely on the trimmer warnings. We run the trimmer in a special way (similar to building an app using the libraries as mentioned above) and gather all warnings from the BCL. We then go and fix those warnings. In cases where the fix is complex/tricky we add a special trimming test - for example. These tests are basically tiny apps which are published with trimming and executed. |
@vitek-karas is there some doc describing how 3-rd parties can run the trimmer this way? |
The above page has that info - the runtime doesn't run it this exact way, but that's because runtime is special in many ways. We know it's not exactly user friendly right now... working on it... |
My bad. Not enough coffee. Missed the link. Thank you for the information! |
@vitek-karas is Where we do use some reflection, in some cases it's for potentially critical components. One solution, if we go down this route, is to document that those components are not supported in trimmed environments, but if we can make it work that would be ideal. I know for most of our assemblies we are still trying to avoid multi-targeting. |
They are just like nullable attributes only recognized by |
Since .NET7 now uses Does anyone know if NET7 linker will skip triming assemblies that specifies this attribute:
Right now the NET7 will perform the full trimming by default, and give a small IL2104-warning about something was discovered during trimming. All errors from the vague warning, can then be discovered during runtime as real errors. |
That is only the default for console apps, other types of apps may have different defaults (for example MAUI, Xamarin, Blazor all default to
|
Would be lovely if you could update documentation about this, since everything is very vague at the moment: https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options https://github.com/dotnet/linker/blob/main/docs/design/trimmed-assemblies.md |
That's actually not true - the only supported value right now is Thanks for the feedback - I opened dotnet/docs#30790 to track the doc improvement. |
In case this helps, you can set |
You're right @sbomer - I confused this with the MSBuild |
So it is impossible to mark an assembly as IsTrimmable=false?
Library maintainers (both open source and at Microsoft) are going to have fun explaining why their nuget-package are throwing unknown type exceptions.
|
Is that for anything built with net7.0 (which we don't do yet) or that targets it? Presumably the latter, but want to confirm. Still, while we do make little use of reflection like Pavel noted above, we still use it in some places e.g., Azure.Security.KeyVault.Keys for some of the cryptographic operations not defined by netstandard2.0 but available in roughly equivalent runtimes. /cc @jsquire @pallavit if we want to act on this for semester planning. |
I don't think that's the right view on this:
Side note: There are ways to tell the system to not trim an assembly already - it's just not an attribute. There's one way in MSBuild, and then there's a way to embed a certain specific XML (linker descriptor) into the assembly to do the same. But we generally don't tell people about these because in most cases it's not the way to solve the problem (as mentioned above). |
What exactly is the current ask then? If people build with the net7.0 SDK, it sounds as if there's nothing more that needs to be done. Application developers using the SDK should get warnings (we could test that) if reflection is used. Do they get actionable output to help them make sure the right types aren't trimmed? For example, if an application used the |
Sounds like the beginning of a good treasure hunt. With hidden doors you can only open if you are Harry Potter.
Not sure I fully understand the argument, that if not everyone can figure out how to use the hammer, then no one can hold it.
What about making an assembly attribute that disables full trimming for the entire application. And only allows the application to perform partial trimming?
|
The static analysis can't figure out which types are needed - if it could, it would be able to keep them and avoid warning the user. The warnings are produced when the static analysis doesn't know what the code is doing - so all it can tell is "This code here is doing something which I don't understand". If this warning occurs in one of the Azure SDK assemblies there's little the end user can do about it:
The ask here is to enable trim analysis (mentioned in the docs) and see what kind of warnings are produced from within the Azure SDK Code and try to fix them. Once that is done, mark the assemblies as trimmable (not that important in .NET 7 anymore). Note that "try to fix them" can generally mean two things:
|
Early on, we could provide a configuration file with reflection-referenced types. Do I correct assume this is the file mentioned above that the .NET doesn't want to publicize? On a related note, @jsquire @pallavit we should revisit multi-targeting, which would also help solve this problem. I'll start a thread offline. |
It is fine to use reflection with trimming as long as the code that uses reflection is annotated or follows idiomatic patterns that are recognized by the linker. For example, the following code is using idiomatic patterns - the linker will keep the named types around as if they were referenced statically: azure-sdk-for-net/sdk/core/Azure.Core/src/Shared/DiagnosticScope.cs Lines 369 to 373 in 6b7a014
The ask is to set
|
That's definitely possible to add, but I don't see much value in it. The "partial" trimming is just a heuristic which makes a simple assumption "Most reflection code acts on user code, so if we don't trim user code, it won't break that much". The example of the crypto algorithms above is exactly the counter example to this assumption - since it's using reflection to access non-user code. Also it's not a very good strategy going forward - maybe it would make most apps using this assembly work, but it's fragile and any change to the code in the assembly or improvements to the tooling can break the app again (one of the reasons we're trying to move away from the "partial" trimming). |
Yes - but if we're going to do any work on this, it would be better to do this "in the code" as it's more maintainable, the configuration file should really be the last resort solution as it's really easy to forget about and break in future changes. |
Think .NET7 should perform full-trim by default, but when detecting assemblies with warnings, then it should only perform partial triming of the assembly, unless the assembly is explictly marked |
@snakefoot ignoring the fact that it would be relatively tricky to implement, it's incorrect and would not help much really. As mentioned above any warning is potentially a "global" problem, which can't be fixed by not trimming the assembly where it came from. Again with the example above, not trimming the SDK assembly won't help if the trimmer decides to remove framework type because it can't see it being used by anything. |
Some libraries, like the Key Vault client libraries, will need to multi-target to remove reflection. See my comment for reasoning. I recommend just multi-targeting |
@heaths Just to make sure: reflection in general is not a problem. What is a problem is reflection that cannot be statically analyzed. Reflection lightup is usually in the form of:
What is not fine is if the types/members reflected on cannot be statically seen. This typically happens when the above straightforward dataflow is interrupted and e.g. the intermediate
If you specify the |
@MichalStrehovsky we do exactly that for performance gains, or has that not been a problem of late? We do target netstandard2.0, so net461 and netcoreapp2.0 are possible customer targets, so I'm concerned about older runtimes as well. Here's an example: azure-sdk-for-net/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/PemReader.cs Lines 17 to 34 in 124a959
From your description, I'd take it that's a problem? Is there any sort of annotations (attributes, |
That should not be a problem. The The problematic case would be something like: class Foo
{
static Type s_type = typeof(ECDsa);
static MethodInfo GetImportPkcs8PrivateKeyMethod() => s_type.GetMethod("ImportPkcs8PrivateKey");
} i.e. the type being reflected on and the name of the member crosses a method boundary/field boundary. Sometimes people write code that way. It is hard to programmatically analyze (it might even be more difficult for human) and trimming doesn't attempt to do that. It can be trivially rewritten to the pattern you already have - that pattern poses no problem for trimming. |
@MichalStrehovsky @eerhardt is this still needed after all the work @m-redding has been doing with AOT? I'm not sure how, or even if, this fits in anymore. |
We've been moving away from "partial" trimming, where the So I'd say, if possible, this work should still be done. I'd expect to use Azure SDK libraries in MAUI apps. However a higher priority would be to address the trimming and AOT warnings from the libraries (i.e. what @m-redding has been doing). |
@jsquire I believe some of the work that @m-redding is doing is similar to this? Please correct me if I am mistaken. |
@pallavit it's related but it's different so I think this issue should remain open. I don't think any of our libraries can be marked as IsTrimmable right now since we had to baseline some unresolvable warnings from Azure.Core. |
Hi @MichalStrehovsky, we deeply appreciate your input into this project. Regrettably, this issue has remained inactive for over 2 years, leading us to the decision to close it. We've implemented this policy to maintain the relevance of our issue queue and facilitate easier navigation for new contributors. If you still believe this topic requires attention, please feel free to create a new issue, referencing this one. Thank you for your understanding and ongoing support. |
1 similar comment
Hi @MichalStrehovsky, we deeply appreciate your input into this project. Regrettably, this issue has remained inactive for over 2 years, leading us to the decision to close it. We've implemented this policy to maintain the relevance of our issue queue and facilitate easier navigation for new contributors. If you still believe this topic requires attention, please feel free to create a new issue, referencing this one. Thank you for your understanding and ongoing support. |
Library or service name.
All libraries.
Is your feature request related to a problem? Please describe.
I've filed this as Azure/azure-libraries-for-net#1274 where our customer hit it, but this is probably applicable to a lot of the SDK assemblies.
I work on the .NET Runtime team and one of the customers I was working with had trouble with excessive size of their app. Looking at their app, I saw that a lot of the big assemblies in their app are produced in this repo (e.g. Microsoft.Azure.Management.Network.Fluent.dll that has 4.7 MB).
The customer was using the PublishTrimmed .NET SDK option to remove unnecessary code from their app. By default, the .NET SDK removes unused code only from libraries that manifest themselves as trimming friendly. This is to prevent breaking code that uses unpredictable reflection (and might end up reflecting on parts of the program that were trimmed).
It would likely a be a good idea to manifest the Azure SDK libraries that are not particularly reflection heavy as trimming friendly. Manifesting them as such is easy - one just need to add an
[AssemblyMetadata("IsTrimmable", "True")]
attribute. The entire process is described at https://docs.microsoft.com/en-us/dotnet/core/deploying/prepare-libraries-for-trimming. Would it be possible to mark the SDK libraries as such? It would be especially helpful for libraries that are over 1 MB, but everything helps.Cc @vitek-karas @sbomer who work on IL Trimming in .NET.
The text was updated successfully, but these errors were encountered: