WPF warm AppDomain startup performance (Application.RunInternal, XamlReader.LoadBaml)
Asked Answered
D

1

3

I have relatively simple application, but warm (second, etc.) start-up time is awful 3-5 seconds. Profiler (VS2010, CPU Sampling) shows that more than 80% of time is spent in Application.RunInternal (~40%) and XamlRader.LoadBaml (~40%) functions.

The root of the problem is that Window is created in non-default AppDomain. If I move Window creation to default AppDomain or give AppDomain unrestricted permission set everything is as fast as expected.


I'm testing on:

  • Windows Seven x64
  • .Net 4.0
  • 4Gb RAM
  • GeForce 9800GT 1Gb.

I'm creating AppDomain this way

var permissionSet = new PermissionSet(null);

permissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution | SecurityPermissionFlag.SerializationFormatter | SecurityPermissionFlag.UnmanagedCode));
permissionSet.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
permissionSet.AddPermission(new UIPermission(PermissionState.Unrestricted));
permissionSet.AddPermission(new MediaPermission(PermissionState.Unrestricted));
permissionSet.AddPermission(new FileDialogPermission(PermissionState.Unrestricted));

var appDomainSetup =
    new AppDomainSetup
    {
        ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
        ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
        DisallowApplicationBaseProbing = false,
        DisallowBindingRedirects = true,
        DisallowCodeDownload = true,
        DisallowPublisherPolicy = true,
        LoaderOptimization = LoaderOptimization.MultiDomainHost
    };

_appDomain =
    AppDomain.CreateDomain(
        name,
        null,
        appDomainSetup,
        permissionSet,
        new[]
    {
        // a few types I need
        typeof(...).Assembly.Evidence.GetHostEvidence<StrongName>(),
    });

The behavior remains the same even if I strip down XAML to empty window

<Window
    x:Class="Rosmurta.Extensibility.WpfUI.RosmurtaWindow"
    x:ClassModifier="internal"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test"
    Height="480"
    Width="640"
    WindowStyle="SingleBorderWindow">
    <Grid>
    </Grid>
</Window>

Not too much to parse by XamlRader.LoadBaml, but it spends more than 30% of startup time event for empty window.


I've tried (and it did not help)

  • Adding <generatePublisherEvidence enabled="false"/> to App.config.
  • Adding [LoaderOptimization(LoaderOptimization.MultiDomainHost)] atribute to Main method.
  • Adding signatures to all assemblies.

What else can be done?

Discriminative answered 30/9, 2011 at 11:58 Comment(7)
Hi, how's about stepping into the actual calls?Liva
@Dmitry, these are methods in PresentationFramework.dll. Even if I'll somehow step into them I can't profile them.Discriminative
tough, but you can't hire Rob Relyea, can ya?:) even then - the first question he's gonna ask is why do you need to load your app in a separate AppDomain?:) "3-5 seconds" delay should be tangible enought to catch it the reason when debugging, which to me seem to be the only viable option.Liva
The answer is simple, the security. As you can see from source code, I provided, there are some CAS restrictions applied. What I can't understand is that there are no first chance exceptions or some other signs of the problem, code is simply slower in restricted domain. In non-restricted non-default domain everything is fast, so CAS is the reason, directly or indirectly. I will keep trying to debug this, just thought somebody may have the answer.Discriminative
so, you are saying that you can't you repro the problem just by loading your app in a separate appdomain? is there a particular CAS setting which badly affects the performance? - knowing it you can step into the .net code and see what's going on out there. sorry for the broad answer but that's the only way I can see.Liva
I can reproduce the problem by using WPF in CAS-restricted AppDomain. Strange thing is that CAS permissions do not affect WPF the way I expect, there are no first-chance exceptions. Code becomes just slower. So I have no idea absence of which CAS permission is affecting the performance.Discriminative
If it's written with .net could you post a quick repro - i can have a look.Liva
C
1

The question is very old, but probably my answer will help somebody. Sometimes XAMLReader definitely takes much time during startup, however this doesn't always mean that the issue is caused by parsing itself. When XAML is being parsed, XAMLParser executes several relatively heave operations except for parsing:

  • Uses reflection to get unknown types and crate instances
  • Initializes objects and creates instances. If your XAML (or XAML of the component library you are using) contains many custom classes, they are created by XAMLParser and jitting occurs.
  • Searches resources in the resource dictionary hierarchy and moreover. If the hierarchy of resource dictionaries is really complex, this operation make take some time.

There are several general techniques that may help you decrease your WPF application startup time:

  • Generate native images using the Ngen tool.
  • Enable MultiCore JIT when Ngen is not applicable
  • Use ReadyToRun in conjunction with MultiCore JIT for .NET Core projects, since there is no Ngen for them
  • Load Data on Demand. I think is is not your case, but may be useful for the full picture. For example, DevExpress has Virtual Source and Server Mode features to do this asynchronously for you.
  • You can also wrap "heavy" views in in controls that delay their loading without freezing the UI. For example, you can use DevExpress LoadingDecorator
  • Make sure that your view controls are not expanded of outside the visible area. For example, if you have StackPanel with ListBox inside, ListBox will create all its elements at once, because StackPanel doesn't limit height for its children, and they "think" that they have infinite height. As a result, ListBox will create all visual elements at once and significantly decrease your performance.
  • As simple way to determine bottlenecks, you can comment UI, you can comment our XAML parts and see how this affects startup

Here is a blog post that might be helpful: 9 Tips to Reduce WPF App Startup Time

Costly answered 27/1, 2023 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.