Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Debug-mode linker improvements
Browse files Browse the repository at this point in the history
~~ StripEmbeddedLibraries ~~

I have noticed the support libraries from NuGet are fairly large. In
total I have seen them around 8MB in size! Much of their size is not
in fact managed code, but the Android resources, jar files, etc.
contained within them.

For example, if you look at the size of
`__AndroidLibraryProjects__.zip` embedded in
Xamarin.Android.Support.v7.MediaRouter 27.0.2.1:

    592534 __AndroidLibraryProjects__.zip

~0.5MB in a single assembly!

So I did an experiment to run the `StripEmbeddedLibraries` linker step
during a debug build.

    Before:
    9.66 MB total
      22064 FormsViewGroup.dll
     101376 HelloForms.Android.dll
       6144 HelloForms.dll
      35416 Xamarin.Android.Arch.Core.Common.dll
      55904 Xamarin.Android.Arch.Lifecycle.Common.dll
      31840 Xamarin.Android.Arch.Lifecycle.Runtime.dll
      77432 Xamarin.Android.Support.Animated.Vector.Drawable.dll
     151648 Xamarin.Android.Support.Annotations.dll
    1699408 Xamarin.Android.Support.Compat.dll
     545880 Xamarin.Android.Support.Core.UI.dll
     228952 Xamarin.Android.Support.Core.Utils.dll
     744528 Xamarin.Android.Support.Design.dll
     409688 Xamarin.Android.Support.Fragment.dll
     733280 Xamarin.Android.Support.Media.Compat.dll
     322648 Xamarin.Android.Support.Transition.dll
      41544 Xamarin.Android.Support.v4.dll
    1995872 Xamarin.Android.Support.v7.AppCompat.dll
      60504 Xamarin.Android.Support.v7.CardView.dll
     780896 Xamarin.Android.Support.v7.MediaRouter.dll
      68184 Xamarin.Android.Support.v7.Palette.dll
     851552 Xamarin.Android.Support.v7.RecyclerView.dll
      61024 Xamarin.Android.Support.Vector.Drawable.dll
     673336 Xamarin.Forms.Core.dll
     334416 Xamarin.Forms.Platform.Android.dll
      16960 Xamarin.Forms.Platform.dll
      85560 Xamarin.Forms.Xaml.dll

    After:
    5.60 MB total
      12800 FormsViewGroup.dll
     101376 HelloForms.Android.dll
       6144 HelloForms.dll
      16896 Xamarin.Android.Arch.Core.Common.dll
      28160 Xamarin.Android.Arch.Lifecycle.Common.dll
      13824 Xamarin.Android.Arch.Lifecycle.Runtime.dll
      32256 Xamarin.Android.Support.Animated.Vector.Drawable.dll
     118784 Xamarin.Android.Support.Annotations.dll
    1142272 Xamarin.Android.Support.Compat.dll
     301568 Xamarin.Android.Support.Core.UI.dll
     123904 Xamarin.Android.Support.Core.Utils.dll
     350208 Xamarin.Android.Support.Design.dll
     231936 Xamarin.Android.Support.Fragment.dll
     411136 Xamarin.Android.Support.Media.Compat.dll
     137216 Xamarin.Android.Support.Transition.dll
      28672 Xamarin.Android.Support.v4.dll
     947200 Xamarin.Android.Support.v7.AppCompat.dll
      28672 Xamarin.Android.Support.v7.CardView.dll
     181248 Xamarin.Android.Support.v7.MediaRouter.dll
      35328 Xamarin.Android.Support.v7.Palette.dll
     497152 Xamarin.Android.Support.v7.RecyclerView.dll
      20480 Xamarin.Android.Support.Vector.Drawable.dll
     673336 Xamarin.Forms.Core.dll
     334416 Xamarin.Forms.Platform.Android.dll
      16960 Xamarin.Forms.Platform.dll
      85560 Xamarin.Forms.Xaml.dll

This equates to:
- 4.0 MB less assemblies shipped to the device during deployment!
- 4.0 MB less assemblies loaded at startup!

Changes to make this happen:

- For this to work properly, I had to change `StripEmbeddedLibraries`
  to operate on `Skip` assemblies. If the assembly is going to get
  stripped, then its action will change to `Save`. This now means this
  pass has to run *last*, so a comment seemed ideal in the list of
  linker steps.

~~ Results ~~

The same "Hello World" Xamarin.Forms project had a minor improvement
to the initial deployment:

    Before:
    2730 ms  InstallPackageAssemblies                   1 calls
    After:
    2549 ms  InstallPackageAssemblies                   1 calls

Saved ~200ms during the first deployment.

And if you review the size of the assemblies copied during
`InstallPackageAssemblies`:

    Before:
    100% ... 10332kb of 10332kb copied
    After:
    100% ... 6173kb of 6173kb copied

TODO: I need to measure startup time impact.
  • Loading branch information
jonathanpeppers committed Jan 10, 2019
1 parent acb72d9 commit e4fbbdb
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ static Pipeline CreatePipeline (LinkerOptions options)

if (options.LinkNone) {
pipeline.AppendStep (new FixAbstractMethodsStep ());
pipeline.AppendStep (new StripEmbeddedLibraries ());
pipeline.AppendStep (new OutputStep ());
return pipeline;
}
Expand Down Expand Up @@ -113,6 +114,7 @@ static Pipeline CreatePipeline (LinkerOptions options)
// monodroid tuner steps
if (!string.IsNullOrWhiteSpace (options.ProguardConfiguration))
pipeline.AppendStep (new GenerateProguardConfiguration (options.ProguardConfiguration));
//NOTE: StripEmbeddedLibraries should run last since Skip assemblies might change to Save
pipeline.AppendStep (new StripEmbeddedLibraries ());
// end monodroid specific
pipeline.AppendStep (new RegenerateGuidStep ());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ protected override void ProcessAssembly (AssemblyDefinition assembly)
if (!Annotations.HasAction (assembly))
return;
var action = Annotations.GetAction (assembly);
if (action == AssemblyAction.Skip || action == AssemblyAction.Delete)
if (action == AssemblyAction.Delete)
return;

var fileName = assembly.Name.Name + ".dll";
Expand All @@ -33,7 +33,7 @@ protected override void ProcessAssembly (AssemblyDefinition assembly)
}
}
}
if (assembly_modified && action == AssemblyAction.Copy) {
if (assembly_modified && (action == AssemblyAction.Copy || action == AssemblyAction.Skip)) {
Annotations.SetAction (assembly, AssemblyAction.Save);
}
}
Expand Down

0 comments on commit e4fbbdb

Please sign in to comment.