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

Linking out formatting code #923

Open
vargaz opened this issue Jan 22, 2020 · 4 comments
Open

Linking out formatting code #923

vargaz opened this issue Jan 22, 2020 · 4 comments
Milestone

Comments

@vargaz
Copy link
Contributor

vargaz commented Jan 22, 2020

Most of the code remaining in a linked hello world is related to formatting, i.e. ToString() overrides.
DateTime.ToString () alone keeps alive about 100k of IL.

Linking these out automatically is very hard. The BCL is full of calls of Object.ToString () on a receiver
whose type is hard to determine at linking time, like elements of object[].

  • For reference types, if there are no instances of the type, the overrides are removed already.
  • There are valuetypes with significant formatting code like DateTime. Removing their overrides would
    require proving that they have no boxed instances, which is very hard because of generics, i.e. for
    every box T, it needs to be proven that T is not a given valuetype.

Probably the best solution right now would be to add some kind of user option, i.e:

  • remove these ToString () methods (via the substitution mechanism)
    or
  • keep these ToString () methods.
@MichalStrehovsky
Copy link
Member

would require proving that they have no boxed instances, which is very hard because of generics

I remember looking into DateTime formatting in the context of CoreRT (that uses pretty much the same CoreLib as Mono). The CoreRT compiler has a natural treeshaker: the compilation is about building a dependency graph so unused things get shaken out naturally as part of the compilation. This dependency graph models generic instantiations.

If I recall correctly, the only reason why DateTime (and Decimal :/) formatting still end up being part of a CoreRT hello world is this code (the dependency model doesn't attempt to prove that the typeof won't be passed to an API like GetUninitializedObject or CreateInstance). I never got around to doing the couple line refactor to take the uncommonly used types out of the commonly used cctor (it is like 50-100 kB of native code, I don't remember the exact number).

So actually analyzing generics would likely fix this. The only hard part about analyzing generics is dealing with deep generics/recursion. CoreRT doesn't have that yet, but the .NET Native dependency analyzer handles that because it's a shipping product. There's tech to steal from.

@marek-safar
Copy link
Contributor

You can today substitute any method body with throw like behaviour but I am not sure what rule we could use for that.

I think we could still do the same for value types as we do for references if we keep tracking value-type locals (the value type is never instantiated if its type never shows up as local variable).

We might end up implementing generics expansion to support better reflection CreateInstance but that could be quite expensive to run for all assemblies and it'd not be my preferences as a general solution.

@mrvoorhe
Copy link
Contributor

We should try and get CodeOptimization.UnreachableBodies turned on by default. It can help to remove some overrides such as ToString. There is an open issue on this feature being enabled in the mono build but I’m fairly certain this is some unannotated native or reflection usage in mono runtime or class libraries rather than anything being broken with the CodeOptimization feature.

@mrvoorhe
Copy link
Contributor

Another interesting scenario I’m aware of that contributes to size and could prevent some existing override removal or stubbing mechanisms from helping is the fact that we mark all fields that are assigned in constructors even if all usages of the field are linked away.

I prototyped delaying processing of field assignments until a usage of the field has been marked and then ripping out the assignments if the field is never loaded. It can help knock other things in a variety of ways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

No branches or pull requests

6 participants