IT资讯-网络猪商务中心
 首页  评论  硬件  数码 笔记本 软件  通信  评测 
您的位置:软件 > 开发者网络 > 微软开发专栏 > 技术专题 > 正文
高性能托管应用程序设计入门
[文章信息]
作者:Gregor Noriskin
时间:2003-08-28
出处:微软
责任编辑:方舟
[文章导读]
学习如何找出托管代码性能的最佳方法,以及如何测量托管应用程序的性能......
advertisement
热点推荐
· 天极网软件频道改版调查
· 在ASP.NET程序中创建唯一序号
· 用JVM工具接口创建调试和分析代理
· Win 2000如何安装配置防火墙
· 防范Windows消息钩子的侵入
[正文]

上一页  1 2 3 4 5 6  下一页

  清理模式 (Dispose Pattern)

  当对象的生命周期不明确时,应该尽快释放与该对象关联的非托管资源。这一过程称为“清理”对象。清理模式通过 IDisposable 接口实现(尽管您自己实现也很容易)。如果您希望对类应用终结,例如,要使类实例可清理,就需要让对象实现 IDisposable 接口并执行 Dispose 方法。使用 Dispose 方法您可以调用终结器中的同一段清除代码,并通知 GC 不需要通过调用 GC.SuppressFinalization 方法来终结该对象。最好同时使用 Dispose 方法和终结器来调用通用终结函数,这样就只需要维护一份清除代码。而且,如果对象的语义为:Close 方法比 Dispose 方法更符合逻辑,那么还应实现 Close 方法,在这种情况下,数据库连接或套接字逻辑上都被“关闭”。Close 可以只是简单地调用 Dispose 方法。

  使用终结器为类提供 Dispose 方法始终是一种很好的做法,因为永远没有人能确切地知道使用类的方法,例如,是否可以明确知道它的生命周期。如果您使用的类实现了清理模式,而且您也确切地知道何时清理好对象,最好明确地调用 Dispose。

  提示:请为所有可终结的类提供 Dispose 方法。

  提示:请将终结操作隐藏在 Dispose 方法中。

  提示:请调用通用清除函数。

  提示:如果您使用的对象实现了 IDisposable,并且您知道已不再需要该对象,请调用 Dispose 方法。

  C# 提供了一种非常方便的自动清理对象的方法。使用关键字 using 来标记代码块,之后,将对大量可清理对象调用 Dispose。

  C# 的 using 关键字

using(DisposableType T)
{
//对 T 执行一些操作
}
//自动调用 T.Dispose()

  弱引用注释

  在堆栈中、寄存器中、其他对象上或某一其他 GC 根对象上,对对象的任何引用都会使得该对象在执行 GC 期间保持存活。一般来说,这是一件好事,因为这通常都表示应用程序不是借助该对象来执行的。然而,有些时候您会需要引用某个对象,但又不想影响其生命周期。在这种情况下,CLR 为实现这一目的而提供了一种称为“弱引用”的机制。任何强引用(例如,以对象为根的引用)都可以转换成弱引用。例如,当您需要创建可以遍历数据结构的外部游标对象,但又不影响该对象的生命周期时,可能需要使用弱引用。又例如,当您需要创建一个存在内存压力时就会刷新的缓存时也可能会需要使用弱引用,例如,发生 GC 时。

  在 C# 中创建弱引用

MyRefType mrt = new MyRefType();
//...

//创建弱引用
WeakReference wr = new WeakReference(mrt);
mrt = null; //对象不再是根对象
//...

//对象是否已回收?
if(!wr.IsAlive)
{
//获得该对象的强引用
mrt = wr.Target;
//对象为根对象而且可以再次使用
}
else
{
//重新创建该对象
mrt = new MyRefType();
}

  托管代码和 CLR JIT

  托管程序集是托管代码的分发单位,它由 Microsoft 中间语言(MSIL 或 IL)构成,适用于所有的处理器。CLR 的实时 (JIT) 功能可将 IL 编译成优化的本机 X86 指令。JIT 是一种执行优化操作的编译器,但是由于编译是在软件运行时进行的,并且仅当第一次调用方法时才会进行,因此进行优化的次数需要与执行编译所花费的时间保持平衡。通常,这对于服务器应用程序并不重要,因为启动时间和响应对于它们来说通常都不构成问题;但对于客户端应用程序来说,却十分重要。请注意,安装时可以通过使用 NGEN.exe 执行编译来加快启动时间。

  许多由 JIT 执行的优化操作都没有与其关联的编程模式,例如,您无法对它们进行显式编码,但是也有一些优化操作具有关联的编程模式。下一节将讨论后者中的部分操作。

  提示:使用 NGEN.exe 实用程序在安装时编译应用程序,可以加快客户端应用程序的启动时间。

  方法内联

  所有的方法调用都会带来开销。例如,需要将参数推入栈中或存储在寄存器中,需要执行的方法起头 (prolog) 和结尾 (epilog) 等。只需要将被调用方法的方法主体移入调用方的主体,就可以避免某些方法的调用开销。这一操作称为方法内联。JIT 使用大量的探测方法来确定是否应内联某个方法。下面是其中一些比较重要的探测方法的列表(请注意这并不是一个详尽的列表):

   IL 超过 32 字节的方法不会内联。

   虚函数不会内联。

  包含复杂流程控制的函数不会内联。复杂流程控制是除 if/then/else 以外的任意流程控制,在这种情况下,为 switch 或 while。

  包含异常处理块的方法不会内联,但是引发异常的方法可以内联。

  如果某个方法的所有定参都为结构,则该方法不会内联。

  我会认真考虑一下对这些探测方法进行显式编码的问题,因为在以后的 JIT 版本中它们可能会有所变化。请不要为了确保方法可以内联而放弃方法的正确性。您也许已经注意到了一个有趣的现象,C++ 中的关键字 inline 和 __inline 不能保证编译器将一种方法内联(尽管 __forceinline 可以)。

  一般情况下,属性的 Get 和 Set 方法都非常适合内联,因为它们主要用于初始化私有数据成员。

  提示:请不要为了试图保证内联而放弃方法的正确性。

  去除范围检查

  托管代码有许多优点,其中一项是可以自动进行范围检查。每次使用 array[index] 语义访问数组时,JIT 都会进行检查以确保索引在数组范围中。在具有大量迭代和少量由每个迭代执行的指令的循环环境中,范围检查的开销可能会很大。在某些情况下,JIT 也可能会在检测到这些范围检查不必要时将其从循环体中删除,即仅在循环开始执行之前对其进行一次检查。在 C# 中有一种编程模式,用来确保这些范围检查会被删除:对“for”语句中数组的长度进行的显式测试。请注意,只要此模式中存在细微的偏差都会导致检查无法去除,在这种情况下,需向索引中添加一个值。

  在 C# 中去除范围检查

//范围检查将被去除
for(int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(myArray[i].ToString());
}

//范围检查将无法去除
for(int i = 0; i < myArray.Length + y; i++)
{
Console.WriteLine(myArray[i+x].ToString());
}

  搜索大型不规则数组时,优化操作特别明显,因为此时将同时删除内循环和外循环范围检查。

  要求进行变量使用情况跟踪的优化操作

  大量 JIT 编译器优化操作都要求 JIT 跟踪定参和局部变量的使用情况,例如,它们在方法主体中的最早以及最近一次使用的时间。在 CLR 1.0 和 1.1 版中,JIT 可以跟踪使用情况的变量总数限制在 64 个之内。例如“寄存操作”就是一个需要进行使用情况跟踪的优化操作。寄存操作是指将变量存储在处理器寄存器中,而不是栈框架中(例如,在内存中)。与对栈框架中的变量进行访问的时间相比,对寄存变量的访问要快得多,即便框架中的变量位于处理器的缓存中也一样。只能对 64 个变量进行寄存,所有其他变量都将推至栈中。除寄存操作以外,另外也有一些优化操作需要进行使用情况跟踪。应该将方法中的定参和局部参数的数量保持在 64 个以下,以确保实现最大数目的 JIT 优化操作。请记住在以后的 CLR 版本中此数目可能会有所变化。

  提示:使方法保持简短。要这样做的原因有很多,包括方法内联、寄存操作和 JIT 持续时间的需要。

  其他 JIT 优化操作

  JIT 编译器还可以执行大量其他的优化操作:常量和副本传播、循环不变式提升以及若干其他操作。需要用来实现优化的编程模式都是免费的,无需花钱购买。

  为什么我在 Visual Studio 中没有看到这些优化功能?

  当您在 Visual Studio 中使用 Debug(调试)菜单或按下 F5 键启动应用程序时,无论您生成的是发行版还是调试版,所有的 JIT 优化功能都将被禁用。当托管应用程序通过调试器启动时,即使它不是该应用程序的调试版本,JIT 也会发出非优化的 x86 指令。如果您希望 JIT 发出优化代码,那么请从 Windows 资源管理器中启动该应用程序,或者在 Visual Studio 中使用 CTRL+F5 组合键。如果希望查看优化的反汇编程序,并将其与非优化代码进行对比,则可以使用 cordbg.exe。

 提示:使用 cordbg.exe 可以查看 JIT 发出的优化和非优化代码的反汇编程序。使用 cordbg.exe 启动该应用程序后,可以通过键入以下代码来设置 JIT 模式:

(cordbg) mode JitOptimizations 1
// JIT 将生成优化的代码

(cordbg) mode JitOptimizations 0

  JIT 将生成可调试(非优化)代码。


上一页  1 2 3 4 5 6  下一页

·"WAP天极之IT新闻资讯,50万元等你拿"    ·天极WAP之游戏狂图,50万元等你下载


发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容阅读排行榜
  • 微软 .NET Remoting体系结构评估
  • 用.Net Framework设计检查EMail程序
  • 在IE中托管.NET Windows Forms
  • 浅析.Net下的多线程编程
  • 主板超频特色技术GIGA技嘉篇
  • Win 2000如何安装配置防火墙
  • 防范Windows消息钩子的侵入
  • 性价比之选 AGP显卡的告别秀
  • 大学校园生活之聊天也疯狂
  • Fireworks制作GIF动画Banner
  • 金山打击外挂 遭网络游戏玩家起诉
  • 完全公测《开天》掀起滔滔巨浪
  • Advertisement