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

ReflectionXamlMetadataProvider GetXamlType taking more than 17 seconds to execute at app startup #1521

Closed
jimm98y opened this issue Oct 31, 2019 · 11 comments
Labels
area-XamlCompiler bug Something isn't working no-issue-activity team-Markup Issue for the Markup team

Comments

@jimm98y
Copy link

jimm98y commented Oct 31, 2019

Describe the bug
We have a large (104 DLLs and 1 EXE referencing all the DLLs) UWP app that was ported from WPF into UWP. The app uses many custom Xaml controls and forms spread out in ~50 DLLs. In Release with NET Native enabled, the app launches quickly (~3 seconds). In Debug, however, the code execution goes from App.cs into autogenerated XamlTypeInfo.g.cs, there it goes into GetXamlType(string fullName) where it calls Provider.GetXamlTypeByName(Provider being ReflectionXamlMetadataProvider) and at this point it starts loading all 104 DLLs into the memory which takes ~17 seconds on a fairly powerful machine to complete (8-core i7, 32GB RAM, SSD). This makes the UWP app impossible to use in Debug on HoloLens where this method takes ~1 minute to complete, because HoloLens determines that the app is not responding and shuts it down before we get to execute any code.

Steps to reproduce the bug
I guess you need many DLLs that contain a lot of XAML. Unfortunately, I can't share our code base. Then I think the behavior might be related to the following App.xaml.cs we are using:
sealed partial class App : MobileApplication, IServiceProvider

<mvvm:MobileApplication

Basically, we've derived our own App class in order to have our own bootstrap and IoC container. The call into GetXamlTypeByName tries to look for MobileApplication class.

Expected behavior
The call into GetXamlTypeByName should not load all our DLLs into the memory which takes too long and I assume it also uses a lot of reflection. We didn't have this issue before updating to 1809 where all the UWP projects started referencing Microsoft.UI.Xaml.Markup by default.

Screenshots
GetXamlTypeByName

Version Info
Windows 10 1903, UWP app has Min/Target versions set to 1809.

NuGet package version:
Microsoft.NETCore.UniversalWindowsPlatform 6.2.9

Windows 10 version Saw the problem?
May 2019 Update (18362) Yes
October 2018 Update (17763) Yes
April 2018 Update (17134) No
Fall Creators Update (16299) No
Creators Update (15063) No
Device form factor Saw the problem?
Desktop Yes
Mobile No
Xbox No
Surface Hub No
IoT No

Additional context

@msft-github-bot msft-github-bot added this to Needs triage in Controls Triage Oct 31, 2019
@jevansaks
Copy link
Member

There is a compile time flag to turn off the ReflectionMetadataProvider. I can't find the docs on what the property is though. @fabiant3 @danzil can you help?

@jevansaks jevansaks added this to Needs triage in Markup Triage via automation Oct 31, 2019
@jevansaks jevansaks removed this from Needs triage in Controls Triage Oct 31, 2019
@jevansaks jevansaks added area-XamlCompiler bug Something isn't working labels Oct 31, 2019
@danzil
Copy link

danzil commented Oct 31, 2019

We use the reflection metadata provider in debug configs to help speed up incremental builds. For your case, it looks like the large number of dll is actually making things worse, so the best course of action is to disable it using this property in your project that is referencing the dlls.

  <PropertyGroup>
    <EnableTypeInfoReflection>false</EnableTypeInfoReflection>
  </PropertyGroup>

@jimm98y
Copy link
Author

jimm98y commented Nov 4, 2019

Thank you! It helped!

@stevenbrix stevenbrix moved this from Needs triage to Investigate / needs follow-up in Markup Triage Nov 4, 2019
@msft-github-bot msft-github-bot added the needs-assignee-attention Assignee needs to follow-up or investigate this issue label Nov 4, 2019
@stevenbrix
Copy link
Contributor

@RealTommyKlein I'm assigning this to you to see if there is any way this can be improved. Are we able to provide hints to the ReflectionMetadatProvider so that it can more efficiently find types, or maybe figure out which projects might run into this issue and fire warnings?

@danzil danzil removed the needs-assignee-attention Assignee needs to follow-up or investigate this issue label Nov 4, 2019
@danzil danzil moved this from Investigate / needs follow-up to Backlog in Markup Triage Nov 4, 2019
@RealTommyKlein
Copy link
Member

Yes, we can definitely improve the search behavior by following the WinRT naming convention (e.g. when searching for "Foo.Bar.Employee" type, first look for a "Foo.Bar" assembly, then a "Foo" assembly). We can also raise a warning when this would be insufficient because a type violates the naming convention, and there are many assemblies referenced by the project.

@danzil
Copy link

danzil commented Nov 4, 2019

I don't know if the Xaml Compiler should be in the business of raising warnings about how types are organized in assemblies. We could definitely better optimize those lookups.

@stevenbrix
Copy link
Contributor

I don't know if the Xaml Compiler should be in the business of raising warnings about how types are organized in assemblies.

We should definitely optimize our lookup. But if we're shipping a feature that fundamentally degrades the user experience in certain scenarios, and we can detect those scenarios, then I think raising a warning is appropriate.

Actually, activating types in this scenario (when violating WinRT naming conventions) doesn't even work does it? If that's the case, would disabling the feature entirely make more sense?

@danzil
Copy link

danzil commented Nov 6, 2019

We're already having a lot of trouble with MIDL and WinRT imposing these silly assembly naming conventions. Since type activation in .Net does not require it (you can reference a Class Library instead of a Windows Runtime Component), I don't believe the Xaml Compiler should either. We should fix our perf and perhaps warn about the reflection provider not being the right mechanism to use if it really takes that long, but not about how the assembly is organized.

@jevansaks jevansaks added the team-Markup Issue for the Markup team label Nov 7, 2019
@jimm98y
Copy link
Author

jimm98y commented Jul 22, 2020

It looks like the EnableTypeInfoReflection flag has stopped working in VS 2019 16.5.2. The delay at startup is back even though the flag is still present in the startup project's csproj. Additionally, the app started crashing with NullReferenceException looking for type ObservableCollection(object) in Debug (the stack trace points to the ReflectionMetadataProvider). In Release, it works fine without crashing.

@RealTommyKlein
Copy link
Member

Were there any other changes made besides upgrading the version of Visual Studio? In particular, were there any new projects added that are referenced/built by the app, like a WinRT component that serves as a Xaml control library? It's possible another Xaml project that's part of your build and referenced by the main app still has the flag enabled, and would still use the reflection provider.

Otherwise, I'd recommend enabling Diagnostic MSBuild logging (in Visual Studio: Tools -> Options -> Projects and Solutions -> Build and run -> MSBuild project output build verbosity -> Diagnostic). Then rebuild your solution, and in the Build output window, Ctrl+F for EnableTypeInfoReflection and verify they're always set to false (if the value has been overwritten/reassigned, the logs will also indicate that).

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 5 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-XamlCompiler bug Something isn't working no-issue-activity team-Markup Issue for the Markup team
Projects
No open projects
Development

No branches or pull requests

6 participants