此文包含如下内容编程
使用perfmon.exe
跟踪性能,即性能监视器(Performance Monitor)安全
它是Windows
自带的一款分析.NET
应用程序的工具,它以图形的方式来表示从内存管理到JIT性能的方方面面。经过它,咱们也能够知道咱们应用程序所使用的资源的状况。服务器
经过 Win + R
的方式,唤出命令提示符工具。在输入框中输入 perfmon.exe
(在Windows10里面,若是在开始菜单出输入,必定要输入所有字符,不然敲回车时可能运行的是系统推荐的应用),而后回车便可,以下:网络
回车后:数据结构
点击右侧面板中的“绿色加号”,以添加计数器,以下 多线程
能够看到,.NET Framework
应用程序有许多预约义的对象,包括用于内存管理(.NET CLR Memory
)、互操做性(.NET CLR Interop
)、异常处理(.NET CLR Exceptions
)以及多线程处理(.NET CLR LocksAndThreads
)的计数器等多种工具。框架
点击列表中项目右边的“向下箭头”,能够查看该性能对象可以支持的计数器dom
单击要查看的性能计数器。工具
在《选定对象的实例》列表框中,单击<全部实例>,指定要在全局(也就是在整个系统范围内)监视CLR的性能计数器。也能够在《选定对象的实例》列表框中,单击要监视该应用程序的性能计数器的应用程序的名称。性能
选择了对象实例以后,点击对话框右下方的【肯定】按钮,既能够完成添加。
步骤以下图:
除了以上经过其余工具的方式外,咱们也能够在某些状况下(好比只须要测试某一段代码的性能的时候)使用代码的方式来处理,这种状况下,用代码或许更加高效。
.NET 为咱们提供了如下类(命名空间System.Diagnostics
)来作这些事情
PerformanceCounter
:表示 Windows NT
性能计数器组件。使用此类可读取现有的计数器,或自定义更合适的计数器。也能够向自定义计数器写入性能数据PerformanceCounterCategory
: 提供与计数器交互的一些方法PerformanceCounterInstaller
:用于指定 PerformanceCounter
组件的安装程序PerformanceCounterType
:指定PerformanceCounter
计算下一个值(NextValue
)使用的公式示例代码以下:
using System;
using System.Collections;
using System.Diagnostics;
public class App {
private static PerformanceCounter avgCounter64Sample;
private static PerformanceCounter avgCounter64SampleBase;
public static void Main() {
ArrayList samplesList = new ArrayList();
/// 用于建立目录/类别
/// 若是不存在,则须要建立,此时不能当即建立计数器,须要过一下子才能使用
if (SetupCategory())
return;
CreateCounters();
CollectSamples(samplesList);
CalculateResults(samplesList);
}
private static bool SetupCategory() {
if (!PerformanceCounterCategory.Exists("AverageCounter64SampleCategory")) {
CounterCreationDataCollection counterDataCollection = new CounterCreationDataCollection();
// 为目录添加计数器
CounterCreationData averageCount64 = new CounterCreationData {
CounterType = PerformanceCounterType.AverageCount64,
CounterName = "AverageCounter64Sample"
};
counterDataCollection.Add(averageCount64);
CounterCreationData averageCount64Base = new CounterCreationData {
CounterType = PerformanceCounterType.AverageBase,
CounterName = "AverageCounter64SampleBase"
};
counterDataCollection.Add(averageCount64Base);
// 建立目录
PerformanceCounterCategory.Create("AverageCounter64SampleCategory",
"Demonstrates usage of the AverageCounter64 performance counter type.",
PerformanceCounterCategoryType.SingleInstance, counterDataCollection);
return true;
} else {
// 目录已经存在,所以咱们能够进行后续步骤
return false;
}
}
private static void CreateCounters() {
// 建立计数器
avgCounter64Sample = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64Sample", false);
avgCounter64SampleBase = new PerformanceCounter("AverageCounter64SampleCategory", "AverageCounter64SampleBase", false);
avgCounter64Sample.RawValue = 0;
avgCounter64SampleBase.RawValue = 0;
}
private static void CollectSamples(ArrayList samplesList) {
Random r = new Random(DateTime.Now.Millisecond);
for (int j = 0; j < 100; j++) {
int value = r.Next(1, 10);
Console.Write(j + " = " + value);
avgCounter64Sample.IncrementBy(value);
avgCounter64SampleBase.Increment();
if ((j % 10) == 9) {
OutputSample(avgCounter64Sample.NextSample());
samplesList.Add(avgCounter64Sample.NextSample());
} else
Console.WriteLine();
System.Threading.Thread.Sleep(50);
}
}
private static void CalculateResults(ArrayList samplesList) {
for (int i = 0; i < (samplesList.Count - 1); i++) {
// 输出样本信息
OutputSample((CounterSample)samplesList[i]);
OutputSample((CounterSample)samplesList[i + 1]);
// 经过.NET自带方法,计算计数器的值
float counterValue = CounterSampleCalculator.ComputeCounterValue((CounterSample)samplesList[i], (CounterSample)samplesList[i + 1]);
Console.WriteLine($".NET computed counter value = {counterValue}");
}
}
private static void OutputSample(CounterSample s) {
Console.WriteLine("\r\nSample values - \r\n");
Console.WriteLine($" BaseValue = {s.BaseValue}");
Console.WriteLine($" CounterFrequency = {s.CounterFrequency}");
Console.WriteLine($" CounterTimeStamp = {s.CounterTimeStamp}");
Console.WriteLine($" CounterType = {s.CounterType}");
Console.WriteLine($" RawValue = {s.RawValue}");
Console.WriteLine($" SystemFrequency = {s.SystemFrequency}");
Console.WriteLine($" TimeStamp = {s.TimeStamp}");
Console.WriteLine($" TimeStamp100nSec = {s.TimeStamp100nSec}\r\n");
}
}
复制代码
这个小节将对这个计数器列表中很经常使用的计数器进行简要说明
包括如下计数器:
.NET CLR Exceptions
类别包含的计数器提供应用程序引起的异常的相关信息
.NET
异常和转换为.NET
异常的非托管异常(例如,从非托管代码返回的HRESULT
在托管代码中会被转换为异常)。>100
的异常)的指示器。.NET
异常筛选次数。Finally
数量/秒:显示每秒执行的 finally
块的数量。特别注意的是,此计数器只计算有异常执行的 finally
块(即抛出异常以后),不计算正常代码路径上的 finally
块。.NET CLR Interop
(互操做)类别包括的计数器提供应用程序与COM
组件、COM+
服务和外部类型库交互的相关信息
CCW
数目:它显示非托管 COM
代码所引用的托管对象数。CCW
是指正在从非托管 COM
客户端引用的托管对象的代理COM
互操做调用或P-Invoke
调用期间将参数和返回值从托管代码封送至非托管代码(或反之).NET CLR JIT
类别包括的计数器提供的由JIT
编译相关信息
JIT
编译的IL
字节数:从应用程序启动以来,由实时 (JIT
) 编译器编译的微软中间语言 (MSIL
) 字节总数JIT
编译的方法数:从应用程序启动以来JI
T 编译的方法总数。此计数器不包括预先进行
JIT` 编译的方法JIT
所占时间百分比:显示自上次JIT
编译阶段以来JIT
编译所用运行占用时间的百分比JIT
每秒编译的IL
字节数:显示每秒JIT
编译的MSIL
字节数JIT
失败数:自应用程序启动以来JIT
编译器编译失败的方法的高峰数量.NET CLR Loading
(加载)类别包括的计数器提供已加载的程序集、类和应用程序域的相关信息
AppDomain
数:应用程序中加载的应用程序域数量AppDomain
速率:每秒加载的应用程序域的数量AppDomain
的速率:每秒卸载的应用程序域的数量AppDomain
总数:自应用程序启动以来已加载的应用程序域的峰值。AppDomain
总数:显示自应用程序启动以来卸载的应用程序的峰值。若是应用程序域加载和卸载屡次,则此计数器将在每次卸载应用程序域时递增。.NET CLR LocksAndThreads
(锁和线程)类别包括的计数器提供应用程序所使用的托管锁和托管线程的相关信息
CLR
建立和拥有的,用做托管线程的基础线程,的本机操做系统线程数。此计数器的值不包括CLR
在其内部操做中使用的线程;它是操做系统进程中线程的子集。CLR
识别的线程数。这些线程与对应的托管线程对象相关联。CLR
不建立这些线程,但它们在CLR内
至少会运行一次。具备相同线程 ID 的线程不会进行两次计数CLR
识别的线程总数CLR
识别的线程数.NET CLR Memory
(内存)类别包括的计数器提供GC
的相关信息
1
代堆、第 2
代堆和大型对象堆的总和,即垃圾回收堆上分配的当前内存(以字节为单位)GC
句柄数:正在使用的垃圾回收句柄的数量。垃圾回收句柄:CLR
和托管环境外部的资源的句柄0
代回收次数:自应用程序启动以来第0
代对象(即最年轻、最近分配的对象)进行垃圾回收的次数1
代回收次数:自应用程序启动以来第 1
代对象进行垃圾回收的次数2
代回收次数:自应用程序启动以来第 2
代对象进行垃圾回收的次数GC
数:因显式调用 GC.Collect
而执行的垃圾回收次数峰值COM
互操做元数据GC
当前已提交的虚拟内存总量(以字节为单位)GC
当前保留的虚拟内存量(以字节为单位)GC
所占时间百分比:执行上次垃圾回收与执行垃圾回收所用时间的百分比。此计数器一般指示GC
表明应用程序收集和压缩内存所执行的做业Finalize
)任务后,仍然存在垃圾回收对象数。 若是这些对象具备对其余对象的引用,则那些对象也会存在,可是不计入此计数器内0
代堆大小:第 0
代中能够分配的最大字节数;但它不能肯定第 0
代中已分配的字节数0
代提高的字节数/秒:每秒从第 0
代提高到第 1
代的字节数1
代堆大小:第 1
代中的当前字节数(切记,此代中的对象不是直接分配的;这些对象是从之前的第 0
代垃圾回收提高的)1
代提高的字节数/秒:每秒从第 1
代提高到第 2
代的字节数2
代堆大小:第 2
代中的当前字节数,不包括大对象,切记:此代中的对象(不包括大对象)不是直接分配的85000
字节左右的对象视做大对象而且直接在大对象堆中分配;它们不按照级别来提高CLR
进程实例的进程 ID。0
代提高的终止内存:因为等待终结而从第 0
代提高到第 1
代的内存字节数0
代提高的内存:垃圾回收后仍存在并从第 0
代提高到第 1
代的内存字节数1
代提高的内存:显示垃圾回收后仍存在并从第 1
代提高到第 2
代的内存字节数.NET CLR Networking
(网络)类别包括的计数器提供应用程序经过网络发送和接收的数据的相关信息
AppDomain
中的全部 Socket
对象接收到的字节的总数。此数据包括未定义的任何协议信息的TCP/IP
数据AppDomain
中的全部 Socket
对象已发送的字节的累积总数。此数据包括未定义的任何协议信息的TCP/IP数据AppDomain
中已经链接的 Socket
对象的累积总数AppDomain
中的全部 Socket
对象接收到的数据报包的总数AppDomain
中的全部 Socket
对象已发送的数据报包的总数HttpWebRequest
平均生存期:自进程启动以来,AppDomain
中在上一个间隔中结束的全部HttpWebRequest
对象的平均时间HttpWebRequest
平均排队时间:自进程启动以来,AppDomain
中在上一个间隔中结束的全部 HttpWebRequest
对象的平均排队时间HttpWebRequest
/秒:AppDomain
中每秒建立的 HttpWebRequest
对象的数目HttpWebRequest
/秒:AppDomain
中每秒添加到队列的 HttpWebRequest
对象的数量HttpWebRequest
/秒:AppDomain
中应用程序每秒调用 Abort
方法的 HttpWebRequest
对象的数量。HttpWebRequest
/秒:AppDomain
中每秒从服务器接收失败状态码的 HttpWebRequest
对象的数量。其余的网络性能计数器,如:
网络性能计数器包含在两个类别中:
.NET CLR
网络:.NET Framework 2
上引入且在 .NET Framework 2
及更高版本上受支持的原始性能计数器。.NET CLR
网络 4:全部上述套接计数器和 .NET Framework 4
及更高版本上受支持的新的性能计数器.NET CLR Security
(安全性)类别包括的计数器提供公共语言运行时针对应用程序执行的安全检查的相关信息
JIT
) 编译时的特定权限时,执行连接时代码访问安全检查RT
检查所占的时间百分比:自上一次取样以来执行运行时代码访问安全检查所用运行时间的百分比.NET1.0
版本到4.5
,快速分析程序瓶颈,找出影响效率的代码。官方网站上有10
天试用版ANTS
性能分析器是一种用于分析.NET
框架支持的用任何语言编写的应用程序的工具。ANTS
性能分析器能分析全部.NET
应用程序,包括ASP.NET
网络应用程序、Windows
服务和COM+
应用程序。ANTS
性能分析器能在几分钟内识别性能瓶颈,运行很是快速,且响应时,对程序的执行具备最低影响。.NET
内存的优化工具,快速发现内存泄漏问题,而且自动进行内存检测VS
自带的性能分析工具:如图
CPU
、GPU
、内存及性能向导四个选项,选择您想要进行的性能分析,点击【Start/开始】就能够了