Some important driving questions:
Some top-level options:
Any additional thoughts?
Any customer out there particularly invested in / desirous of this?
That's an old dream of mine - to be able in one way or another to include only the relevant parts of assemblies. I absolutely hate when I have to include large >10MB assemblies when only a small fraction of it is actually used (like a few methods or so).
I like the ♯3 suggestion. Maybe it would be possible to combine those small assemblies into one while building.
@ericstj @danmosemsft @stephentoub @JeremyKuhne @sharwell thoughts?
My thoughts on this:
Ideally it will be â„–2 without drawbacks. But I am afraid it's impossible :(
â„–3 looks promising, but wouldn't it lead to mess with many references?
do customers care about small reductions in size or do they want larger reductions?
We don't care about small reductions, we care about whole big size of the self contained deployment.
For now, I think we will continue to install runtimes and stick to not use self contained apps...
At the highest level, my thoughts on this come down to the following two points:
I believe the focus at this point should be on software clarity, reliability, and maintainability. Proper consideration of these will naturally help avoid bloat. Once we are comfortable with the way the software behaves, we can evaluate the build and distribution mechanisms to find low-hanging fruit and target those specifically.
We already do both (1) and (2) in coreclr and corefx, using ILLink as part of the build. Then PublishTrimmed can also be used when creating a self-contained executable to aggressively trim unused functionality (even from framework binaries) when creating the self-contained app.
cc: @jeffschwMSFT
I believe the focus at this point should be on software clarity, reliability, and maintainability.
The problem I see is that it is easy to take it with a bias. The motivation of this issue comes from implementing interop for Windows API which usually is very stable, so one would probably tend to include more than less.
The problem is
I already mentioned it when this was discussed before, but if WinForms feels desire to have "complete" interop APIs it should not make them internal, but instead expose them in a common utility assembly which can be used by 3rd parties.
The bloat happening due to repeated Windows API interop definitions in every single library is unfortunately not measured by anyone, but I assume its something real and significant. The amount of interop WinForms does is significant, if other projects could reuse interop APIs instead of redeclaring them that would be a win for everyone.
If we speculate for a moment that Mono WinForms was to make a return and bring the x-plat aspect back to reality, how do you think our interop layer would change?
Would we ship a single assembly with sets of API targeting multiple OS, or would we ship per-OS assemblies?
Sorry, I have no idea about how to do x-plat interop.
What I'm talking about is Windows only: all major (WinForms) UI suites tend to have significant integration with Windows APIs, add the platform frameworks themselves, and the app building on it. We are using .NET (which would be CoreFX in the future), System.Drawing, WinForms, WPF, ComponentOne, DevExpress, add a few minor 3rd party controls and all the interop in our own application this should have around 5+ duplicates of all common interop APIs.
I know it may not be easy to pull in 3rd parties immediately, but even if just CoreFX, System.Drawing, WinForms, WPF and the application itself share a single interop library thats a significant reduction of duplicate interop declarations.
Since its not really possible to measure its uncertain how much this actually wins, but looking at the big picture it seems like there are improvements to be made by having a common interop library in the framework.
The biggest trick with a shared interop library/libraries is the sheer number of APIs involved and the vast number of ways to interact with them. In my WInterop library I've got 52,000 lines of code and I've only wrapped a relatively small subset of Win32 APIs completely. Most of our libraries only use a small set of APIs and they use them in very specific ways. The superset of APIs needed for Core and WinForms alone wouldn't be trivial.
Wrapping APIs so that they can be used safely and with reasonably high performance requires quite a bit of wrapper code and multiple entry points to for the same functionality or a more complicated model that isn't "pretty" or "easy to use" (see what I did with FileSystemEnumerable/Enumerator<TResult> for an example of exposing high performance entry).
One can address some of size by having multiple assemblies, but that only goes so far without introducing a lot of cognitive complexity for users. Organizing by entry point dll (say user32) doesn't help much as most anything you'll do will cross all of the core windows dlls and they have a vast surface area. Organizing by topic is a bit more workable, but bucketing is somewhat challenging. It's hard to see good buckets without implementing/investigating large swaths of APIs. Rebucketing where APIs live is difficult to do as it is breaking.
I'm not trying to say it is impossible or not worth doing, just that it is challenging and would be a ton of work. It might be worth trying to organize the interop in WinForms into internal assemblies and a structure that we think would be more generally useful as a way to vet the practicality of eventually creating a public set of interop libraries. I've spent the past several years exploring strategies for creating a reusable interop library so have a lot of useful data that we could use in coming up with a design (pros/cons of a variety of options).
We will consider this if we get significant customer feedback. There is significant risk and we've not heard that feedback yet.
Most helpful comment
We already do both (1) and (2) in coreclr and corefx, using ILLink as part of the build. Then PublishTrimmed can also be used when creating a self-contained executable to aggressively trim unused functionality (even from framework binaries) when creating the self-contained app.
cc: @jeffschwMSFT