WPF/Silverlight设计器大量地使用了AppDomain。在Beta 2的版本下,CLR (Common Language Runtime 公共语言运行时)需要以下的注册表的设置才能够有效率地支持多个AppDomain.
为了得到最佳的性能,您需要在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0下添加Clrhost这个key。然后再添加StartupFlags(类型为DWORD32值为5)。如下图所示:
等到产品正式发布后,这个设置将会是缺省。
在下面的例子中:
<Window xmlns=http://schemas.microsoft.com/winfx/avalon/2005
xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Background="#AA223344" Content ="Button 1" Name="btn1"/>
<Button Background="#AA223344" Grid.Column="1" Content="Button 2" Name="btn2"/>
</Grid>
</Window>
Button1和Button2有着相同的Background,至少在Xaml和在屏幕上看起来如此。但是,Under the hood, 我们看到的是2个不同的SolidColorBrush的实例(instance)。如何能够让2个背景共享一个SolidColorBrush以减少working set(工作集)呢?你可以通过代码,但大多数的情况下我们可以使用Resources.加入:
<Grid.Resources>
<SolidColorBrush x:Key="myBrush1" Color="#AA223344"/>
</Grid.Resources>
然后改写Button的Background,使其通过StaticResource或者DynamicResource引用myBrush1:
<Button Background="{StaticResource myBrush1}" Content ="Button 1" Name="btn1"/>
<Button Background="{StaticResource myBrush1}" Grid.Column="1" Content="Button 2" Name="btn2"/>
在这个简单的示例之中,Button的Background是相对简单的SolidColorBrush。如果使用更复杂的GradientBrush或TileBrush,共享的意义会更大。当然仅从简略Xaml的角度,我们也会在那些情况下使用Resources.
以一道思考题结束:如果不使用Resources,将Button写成
<Button Background="LightYellow" Content ="Button 1" Name="btn1"/>
<Button Background="LightYellow" Grid.Column="1" Content="Button 2" Name="btn2"/>
2个Button会共享同一个SolidColorBrush么?你总是可以通过代码测试的:
if (btn1.Background == btn2.Background)
{
System.Diagnostics.Debug.WriteLine("(1,2) Shared");
}
else
{
System.Diagnostics.Debug.WriteLine("(1,2) Not shared");
}
有人问使用sealed声明密封类(sealed class)对于提高性能有帮助么?答案是肯定的。如果根据设计一个类可以被sealed,则我们应该这样做。
比如说,如果基类(base class)B中定义了虚函数,而sealed class S从B类衍生。对于一个类型为S的名为s的变量调用虚函数的代码,编译器可以确信s一定是类型为S的。但是如果类S实际上没有被sealed,则这个变量s可能是类S的衍生类的实例而这个衍生类同时又重写(override)了该虚函数。这时为了正确性,编译器必须以虚函数调用的方式执行该代码。这比直接执行的成本要高。
另外一个例子是attribute属性类。有一个FxCop的规则(Avoid unsealed attributes)专门检查定义的属性类是不是sealed。除了上面谈及的原因,还特别提到Attribute.GetCustomAttribute的API. 其解释如下:The .NET Framework class library provides methods for retrieving custom attributes. These methods search the attribute inheritance hierarchy by default; for example System.Attribute.GetCustomAttribute searches for the specified attribute type, or any attribute type that extends the specified attribute type. Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance.
关于FxCop的讨论,请参看定制FxCop规则示例之一。
贴子以"现状"提供且没有任何担保也没有授予任何权利
如果在源程序中使用ConditionalAttribute如下所示:
[System.Diagnostics.Conditional("DEBUG")]
public static void OutputInfo()
{
Console.WriteLine("Display Information");
}
那么对其调用的语句只出现在Debug Build之中。然而需要了解的是:即使在Release Build之中,此函数仍然存在于assembly之中。不存在的只是调用此函数的语句。如果这样使用Conditional("DEBUG")的函数很多,它们在Release Build中不必要的存在就会影响性能。比如程序集的size,working set, startup time会增加。建议还是使用#if DEBUG和#endif。
注意System.Diagnostics.Debug.Assert() 的使用将不会对release build的性能有任何不良影响。
贴子以"现状"提供且没有任何担保也没有授予任何权利。
口说无凭,对于性能的优劣必须通过measurement(测量)才能定夺。如何说服客户或者老板将ASP网站升级为ASP.NET网站?提出ASP.NET在性能上显著优于ASP的证据一定会有帮助。
微软请Doculabs公司作了这样的测量,其基准测试结果(PDF File)充分的证明了这一点。这样的基准测试还是很花费人力物力的。
因为这是对来自同一个公司的2个技术的比较,来自其他渠道的资料并不多。如果您有别的相关的文章或者白皮书,请在回复中提及。
(而对来自不同公司的技术比较的材料就比较多了。比如.NET和J2EE。来自微软的内容可以在此处得到。)
Patterns & Practices系列包括了大量极其有用的资料,最佳实践,代码,分析和评估。往往汲取了微软内外的经验和智慧。
最新发布的提高.NET应用程序的性能和可伸缩性就是一个典范。这本书涵盖了建模,衡量,测试和调整托管应用程序的每一步,对使用包括ASP.NET, ADO.NET, Exterprise Services, Web Service等技术时提高性能和可伸缩性提供了实用和专业的指导。
如果你只看一本关于.NET性能的书,就是它了。