WPF温暖的AppDomain启动性能(Application.RunInternal XamlReader.LoadB



我有一个相对简单的应用程序,但是启动时间(秒等)是可怕的3-5秒。分析器(VS2010, CPU采样)显示超过80%的时间花在应用程序上。RunInternal(~40%)和XamlRader。LoadBaml(~40%)函数

问题的根源在于windows是在非默认的AppDomain中创建的。如果我将窗口创建移动到默认的AppDomain或给AppDomain不受限制的权限集,一切都和预期的一样快。


我正在测试:

  • Windows 7 x64
  • 。Net 4.0
  • 4 gb RAM
  • GeForce 9800GT 1Gb.

我这样创建AppDomain

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>(),
    });

即使我将XAML剥离为空窗口

,行为仍然保持不变
<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>

对于XamlRader来说不是太多。LoadBaml,但它花费超过30%的启动时间事件为空窗口。


我试过了(但没有用)

  • 新增App.config。
  • 增加[LoaderOptimization(LoaderOptimization. multidomainhost)]属性到Main方法。
  • 向所有程序集添加签名。

还能做什么?

这个问题很老了,但我的答案可能会对某人有所帮助。有时XAMLReader在启动时确实需要花费很多时间,但这并不总是意味着问题是由解析本身引起的。解析XAML时,XAMLParser执行除解析之外的几个相对复杂的操作:

  • 使用反射获取未知类型和crate实例
  • 初始化对象并创建实例。如果您的XAML(或您正在使用的组件库的XAML)包含许多自定义类,则由XAMLParser创建它们并发生jit。
  • 在资源字典层次中搜索资源。如果资源字典的层次结构非常复杂,则此操作将花费一些时间。

有几个通用的技术可以帮助您减少WPF应用程序的启动时间:

  • 使用Ngen工具生成本地图像。
  • 当Ngen不适用时启用多核JIT
  • 使用ReadyToRun与多核JIT为。net核心项目,因为没有为他们的Ngen
  • 按需加载数据。我认为这不是你的情况,但可能有助于全面了解情况。例如,DevExpress具有虚拟源和服务器模式功能,可以为您异步完成此操作。
  • 你也可以使用"heavy"控件中的视图延迟加载而不冻结UI。例如,你可以使用DevExpress LoadingDecorator
  • 确保您的视图控件没有扩展到可见区域之外。例如,如果你的StackPanel里面有ListBox, ListBox会一次创建它所有的元素,因为StackPanel不限制它的子元素的高度,并且它们会"思考"。它们的高度是无限的。因此,ListBox将一次创建所有的视觉元素,并显著降低你的性能。
  • 作为确定瓶颈的简单方法,你可以评论UI,你可以评论我们的XAML部分,看看这如何影响启动

这里有一篇博客文章可能会有所帮助:缩短WPF应用程序启动时间的9个技巧

最新更新