unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.79k stars 707 forks source link

How to optimize iOS and Android (Net 6) for package size and startup speed (Trimmer and Profile Guided AOT) #11248

Open jeanplevesque opened 1 year ago

jeanplevesque commented 1 year ago

What would you like clarification on:

Now that Xamarin is phasing out, there should be a guide on how to optimize Uno applications with the unified .Net options, especially on mobile platforms (iOS & Android).

There are at least 2 areas of interest.

Trimmer (also referred to as "Linker")

With Xamarin apps, we could set AndroidLinkMode/MtouchLink to Full to remove as much unused code as possible while being able to keep specific items using an linker-exclusion file.

How can we have that package size optimization on .Net 6 mobile apps?

Profile Guided AOT (Android)

With Xamarin apps, we could generate an AOT profile to have the best tradeoff between package size and speed. The profiling phase would allow choosing which parts of the application to optimize to avoid having a package that's too big.

How can we have that package size & speed optimization on .Net 6 mobile apps?

These optimizations are crucial for enterprise-level-quality apps.

Concern?

For which Platform:

Anything else we need to know?

jeromelaban commented 1 year ago

The Linker (trimmer) is working as expected, and in the case mentioned in https://github.com/unoplatform/uno/discussions/11214, this is specifically related to an issue in the runtime (https://github.com/dotnet/runtime/issues/74141).

There's no solution specified in the related changes for that issue, other than saying that generated serializers should be used. The generated serializers solution should be favored for performance reasons.

A workaround can be used though, which is to add the following in the csproj:

    <Target Name="_LinkerAdjust" AfterTargets="_PrepareLinking">
            <!--  Workaround for https://github.com/dotnet/runtime/issues/81979 -->
        <PropertyGroup>
            <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --keep-metadata all</_ExtraTrimmerArgs>
        </PropertyGroup>
    </Target>

This will inject the appropriate options in the linker so that the original .NET issue is not raised. I've opened https://github.com/dotnet/runtime/issues/81979 so that we can track the progress in the runtime.

Note that the linker configuration file should be included as mentioned in the .NET Trimmer documentation (using TrimmerRootDescriptor), not using legacy Xamarin based MSBuild properties and items.

GitHub
How to enable full linker on net6.0-android and net6.0-ios so that Refit and System.Text.Json work? · Discussion #11214 · unoplatform/uno
We're building a mobile net6.0 app using Uno. It uses System.Text.Json (with source generation) and Refit (which also uses source generation). When building with MtouchLink/AndroidLinkMode to F...
Soap-141 commented 1 year ago

Hello @jeromelaban,

I used the workaround you mentioned and it seems to be working except that the application size is the same as the one when the linker is disabled.

Is it possible that it had nothing to remove?

image image image

jeromelaban commented 1 year ago

The linker is working properly:

jeanplevesque commented 1 year ago

@jeromelaban, @Soap-141 tried with PublishTrimmed and TrimMode, not with AndroidLinkMode. @Soap-141 Does the workaround work though? Is the app working correctly?

jeromelaban commented 1 year ago

It may be that AndroidLinkMode must not be mixed with TrimMode, that part is not clear.

Soap-141 commented 1 year ago

I did not use AndroidLinkMode I followed this here.

Soap-141 commented 1 year ago

@jeromelaban, @Soap-141 tried with PublishTrimmed and TrimMode, not with AndroidLinkMode. @Soap-141 Does the workaround work though? Is the app working correctly?

Yes it does work when using PublishTrimmed and TrimMode with the workaround but I don't think it impacted the size.

jeanplevesque commented 1 year ago

Yes it does work when using PublishTrimmed and TrimMode with the workaround but I don't think it impacted the size.

You can unzip the resulting package to better see the difference, if any.

jeromelaban commented 1 year ago

Using the workaround above only gives a very small size difference, as it's only for method parameters.

jeromelaban commented 1 year ago

In recent updates, @Soap-141 mentioned that net7 is helping for this issue, and it's likely that net8 will help some more. Overall, Uno can't do much around linking itself, as those are .NET features. If we notice that specific parts of an app should be trimmed, and are not, it may be interesting to raise an issue directly in dotnet/runtime or dotnet/sdk.

What we can do in Uno, however, is enhance the size reduction with Xaml Trimming in https://github.com/unoplatform/uno/issues/9632.

jeanplevesque commented 1 year ago

In recent updates, @Soap-141 mentioned that net7 is helping for this issue, and it's likely that net8 will help some more. Overall, Uno can't do much around linking itself, as those are .NET features. If we notice that specific parts of an app should be trimmed, and are not, it may be interesting to raise an issue directly in dotnet/runtime or dotnet/sdk.

But that's probably because @Soap-141 disabled AOT as a workaround for other problems. 😕

Soap-141 commented 1 year ago

But it was still better without disabling the AOT, we just had an issue in the application.

Guidemarcus commented 1 year ago

fyi, I know the issue is talking about net6, but while updating to net7, the same behavior is observed.

The fix is the same, but the TrimMode property needs to be set to "partial" instead of "link"

jeromelaban commented 1 year ago

@Guidemarcus when saying "the fix the same", which fix are you talking about?

jeromelaban commented 1 year ago

Note that .NET 7 and .NET 8 are introducing update related to this issue, and if any of the commenters have numbers to share w.r.t the improvements/regressions with .NET 6, please do.