我有一个相对简单的应用程序,但是启动时间(秒等)是可怕的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个技巧