| | | | | | | [文章信息] | | | 作者: | Gregor Noriskin | | 时间: | 2003-08-28 | | 出处: | 微软 | | 责任编辑: | 方舟 | |
| [文章导读] | | | 学习如何找出托管代码性能的最佳方法,以及如何测量托管应用程序的性能...... | |
| |
|
| | | |
|
|
|
|
|
用于分析的API和CLR分析器
CLR 中包含一个功能强大的用于分析的 API,第三方可用它来为托管应用程序编写自定义分析器。CLR 分析器是一种分配分析示例工具,由 CLR Product Team 编写,但不提供技术支持,该分析器使用的就是这种用于分析的 API。开发人员可以使用 CLR 分析器查看其管理应用程序的分配配置文件。
 图 1:CLR 分析器主窗口
CLR 分析器包括大量非常有用的分配配置文件视图,包括:已分配类型的柱状图、分配和调用图表、显示不同代的 GC 和进行这些回收之后托管堆的结果状态的时间线,以及显示各个方法分配和程序集加载情况的调用树。
 图 2:CLR 分析器分配图表
提示:有关如何使用 CLR 分析器的详细信息,请参阅 Zip 文件中包含的自述文件。 请注意,CLR 分析器具有高性能的特点,可以显著地改变应用程序的性能特点。如果您在运行应用程序时也运行了 CLR 分析器,因压力而产生的问题很可能都会消失。
集成服务器 GC
有两种不同的垃圾回收器可供 CLR 使用:工作站 GC 和服务器 GC。控制台和 Windows 窗体应用程序中集成了工作站 GC,而 ASP.NET 中集成了服务器 GC 。服务器 GC 针对吞吐量和多处理器的可扩展性进行了优化。服务器 GC 在整个回收期间(包括标记阶段和清除阶段)会暂停所有运行托管代码的线程,并且 GC 会在可供高优先级的 CPU 专用线程中的进程使用的所有 CPU 上并行执行。如果线程在执行 GC 期间运行了本机代码,那么只有当本机调用返回时这些线程才会暂停。如果您要构建的服务器应用程序将要在多处理器计算机上运行,强烈建议您使用服务器 GC。如果您的应用程序不是由 ASP.NET 提供的,那么您就必须编写一个本机应用程序来显式集成 CLR。
工作站 GC 经过优化,其滞后时间非常短,非常适合客户端应用程序。没有人会希望客户端应用程序在执行 GC 期间出现明显的停顿,这是因为客户端的性能通常都不是通过原始吞吐量,而是通过反应性能来测量的。工作站 GC 是并发 GC,这意味着它会在托管代码运行的同时执行标记阶段。工作站 GC 仅在需要执行清除阶段时才会暂停运行托管代码的线程。在工作站 GC 中,由于 GC 仅在一个线程上运行,因而它只在一个 CPU 上运行。
终结 (Finalization)
CLR 提供一种在释放与类型实例关联的内存之前自动进行清除的机制。这一机制称为终结 (Finalization)。通常,终结用于释放本机资源,在这种情况下,则释放由对象使用的数据库连接或操作系统句柄。
终结是一个开销很大的功能,而且它还会加大 GC 的压力。GC 会跟踪 Finalizable 队列中需要执行终结操作的对象。如果在回收期间,GC 发现了一个不再存活且需要终结的对象,它就会将该对象在 Finalizable 队列中的条目移至 FReachable 队列中。终结操作在一个称为终结器线程 (Finalizer Thread) 的独立线程中执行。因为在终结器的执行过程中,可能需要用到该对象的所有状态,因此该对象或其指向的所有对象都会升级至下一代。与对象或对象图相关的内存仅在执行后续的 GC 时才会释放。
需要释放的资源应该包装在一个尽可能小的可终结对象中,例如,如果您的类需要引用托管资源和非托管资源,那么您应该在新的可终结类中包装非托管资源,并使该类成为您的类的成员。父类不能是可终结类。这意味着只有包含非托管资源的类会被升级(假如您没有在包含非托管资源的类中引用父类)。另外还要记住只有一个终结线程。如果有终结器导致此线程被阻塞,就不能调用后续的终结器,也不能释放资源,而且您的应用程序会导致资源泄漏。
提示:应该尽可能使终结器保持简单,且永远不会阻塞。
提示:仅将需要清除的非托管对象的包装类设为可终结。
可以将终结认为是引用计数的一种替换形式。执行引用计数的对象将跟踪有多少其他对象对其进行引用(这会导致一些非常有名的问题),以便在引用计数为零时释放其资源。CLR 没有实现引用计数,因此它需要提供一种机制,以便在不存在对象的引用时自动释放资源。终结就是这种机制。通常,终结仅需要在要清除的对象的生命周期不明确的情况下执行。
|
|
|
|
|
|
|
|