Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
假设你正在运行 Web 性能测试。 需要跟踪才能了解 Web 应用在负载下运行的方式。 要使 .NET Profiler 能上传跟踪,您的服务必须正常处理请求。 在本文中,您可以:
- 通过启动 Web 性能测试或启动 Profiler 按需会话来为 Web 应用生成流量。
- 完成负载测试或 Profiler 会话后,查看 Profiler 跟踪。
- 了解如何读取 Profiler 性能数据和调用堆栈。
为 Azure 服务生成流量
如果 Azure 服务已有传入流量,或者只想手动生成流量,请跳过负载测试并启动 Profiler 按需会话:
在 Azure 门户中,打开 Application Insights 资源。 在左侧菜单中,选择“ 调查>性能”。
在性能窗格中,从 Profiler 设置的顶部菜单中选择 Profiler。
加载 Profiler 设置页面后,选择“ 立即分析”。
查看踪迹
追踪探查器会显示以下信息:
| 筛选器 | 说明 |
|---|---|
| 个人资料树 v. 火焰图 | 以树状或图形显示踪迹。 |
| 热路径 | 选择以打开最大的叶节点。 大多数情况下,此节点与性能瓶颈相邻。 |
| 框架依赖项 | 选择查看与跟踪关联的每个已跟踪的框架依赖项。 |
| 隐藏事件 | 输入要隐藏在跟踪视图中的字符串。 选择建议的事件以查看建议。 |
| 事件 | 事件或函数名称。 树中显示了代码与发生的事件(例如 SQL 和 HTTP 事件)的混合形式。 最前面的事件表示请求总持续时间。 |
| 模块 | 发生跟踪事件或函数的模块。 |
| 线程时间 | 从操作开始到操作结束之间的时间间隔。 |
| 时间线 | 函数或事件运行的时间相对于其他函数运行的时间。 |
读取性能数据
.NET Profiler 结合使用采样方法和检测来分析应用程序的性能。 在执行详细收集的过程中,.NET Profiler:
每毫秒对每个计算机 CPU 的指令指针进行采样。
每个样本都捕获了线程的整个调用堆栈,其中提供了高层和底层抽象的详细信息。
收集事件以跟踪活动相关性和因果关系,包括:
- 上下文切换事件
- 任务并行库 (TPL) 事件
- 线程池事件
时间线视图中显示的调用堆栈是采样和检测的结果。 每个示例捕获线程的完整调用堆栈。 它包括来自 Microsoft .NET Framework 和你引用的任何其他框架的代码。
对象分配 (clr!JIT_New or clr!JIT_Newarr1)
clr!JIT_New 和 clr!JIT_Newarr1 是 .NET Framework 中的 helper 函数,用于分配托管堆中的内存。
- 分配对象时,将调用 clr!JIT_New。
- 分配对象数组时,将调用 clr!JIT_Newarr1。
这两个函数通常可快速工作。 如果在时间线中发现 clr!JIT_New 或 clr!JIT_Newarr1 占用了时间,这可能表示代码正在分配大量对象,并因此消耗大量内存。
加载代码 (clr!ThePreStub)
Clr!ThePreStub 是 .NET Framework 中的帮助程序函数,用于准备初始执行的代码,通常包括实时 (JIT) 编译。 对于每个 C# 方法,clr!ThePreStub 在一个进程中最多应调用一次。
如果 clr!ThePreStub 针对某个请求花费了额外的时间,则表示这是第一个执行该方法的请求。 .NET Framework 运行时需要大量时间来加载第一个方法。 请注意以下几点:
- 使用在用户访问代码之前运行该部分代码的预热过程。
- 在程序集上运行本机映像生成器(ngen.exe)。
锁争用 (clr!JITutil_MonContention 或 clr!JITutil_MonEnterWorker)
clr!JITutil_MonContention 或 clr!JITutil_MonEnterWorker 指示当前线程正在等待释放锁。 此文本通常在以下情况下显示:
- 执行 C# LOCK 语句
- 调用 Monitor.Enter 方法
- 使用 MethodImplOptions.Synchronized 属性调用方法
如果线程 A 获取了某个锁,而线程 B 在线程 A 释放该锁之前尝试获取同一个锁,此时通常会发生锁争用。
加载代码 ([COLD])
如果 .NET Framework 运行时首次运行 未优化的代码 ,则方法名称包含 [COLD]:
mscorlib.ni![COLD]System.Reflection.CustomAttribute.IsDefined
对于每个方法,在过程中最多应显示一次。
如果请求加载代码需要相当长的时间,则表示该请求首次执行方法的未优化部分。 请考虑使用在用户访问代码之前运行该部分代码的预热过程。
发送 HTTP 请求
HttpClient.Send 等方法指示代码正在等待某个 HTTP 请求完成。
数据库操作
SqlCommand.Execute 等方法指示代码正在等待某个数据库操作完成。
等待 (AWAIT_TIME)
AWAIT_TIME 指示代码正在等待另一个任务完成。 这种延迟会发生在 C# AWAIT 语句上。 当代码执行 C# AWAIT 时:
- 线程展开并将控制权返回到线程池。
- 没有被阻塞的线程等待 AWAIT 完成。
但是,从逻辑上讲,执行 AWAIT 的线程会被阻止,等待操作完成。 AWAIT_TIME 语句指示因等待任务完成而被阻止的时间。
如果AWAIT_TIME显示为框架代码而不是你的代码,则 .NET Profiler 可能会显示:
- 用于运行 AWAIT 的框架代码
- 用于记录有关“AWAIT”的遥测数据的代码
若要仅显示代码并更轻松地查看 AWAIT 的来源,请在页面顶部取消选择 框架依赖项。
阻塞时间
BLOCKED_TIME 表示代码正在等待其他资源变为可用。 例如,它可能在等待:
- 同步对象
- 可用的线程
- 请求完成
非托管异步
为了跨线程跟踪异步调用,.NET Framework 会发出 Windows 事件跟踪(ETW)事件,并在线程之间传递活动 ID。 由于非托管(本机)代码和某些较旧的异步代码样式缺少这些事件和活动 ID,因此 .NET Profiler 无法跟踪线程和线程上运行的函数。
此项在调用堆栈中标记为“非托管异步”。 下载 ETW 文件以使用 PerfView 获取更多见解。
CPU 时间
CPU 正忙于执行指令。
磁盘时间
应用程序正在执行磁盘操作。
网络时间
应用程序正在执行网络操作。
“时间”列
“时间”列是针对节点收集的各种“包含”样本随时间变化的可视化表现。 请求的总范围被划分为 32 个时间段,节点的非独占样本在其中累积。 每个存储桶用一个条形表示。 条形的高度表示缩放后的值。
对于以下节点,条表示存储桶中某个资源的消耗量:
- 标记为 CPU_TIME 或 BLOCKED_TIME 的节点。
- 与使用资源有明显关系(例如 CPU、磁盘或线程)的节点。
如果消耗多个资源,这些指标的值可能大于 100%。 例如,如果在某个时间间隔内平均使用两个 CPU,则将达到 200%。