首页 > 编程语言 >PerfView专题 (第十五篇): 如何洞察 C# 中的慢速方法

PerfView专题 (第十五篇): 如何洞察 C# 中的慢速方法

时间:2023-07-21 13:11:05浏览次数:26  
标签:洞察 C# mytest1 PerfView 慢速 方法 perfview

一:背景

1. 讲故事

在 dump 分析旅程中,经常会遇到很多朋友反馈一类问题,比如:

  • 方法平时都执行的特别快,但有时候会特别慢,怎么排查?
  • 我的方法第一次执行特别慢,能看到慢在哪里吗?

相信有朋友肯定说,加些日志不就好了,大方向肯定是没问题的,但加日志的颗粒度会比较粗而且侵入性也比较大,比如说这个方法不是你的,或者说这个方法是操作系统的,一般情况下对他们无法干涉,那如何洞察在你作用域之外的方法性能呢?作为 CLR团队首推的 PerfView 性能分析工具,必须要 KO 这些问题,接下来我们就简单聊一聊。

二:PerfView 洞察慢速方法

1. 测试代码

为了方便讲述,我们模拟这样的一种情况,一个方法第一次执行会特别慢(5s),后面执行都很快(3s),测试代码如下:


    internal class Program
    {
        static void Main(string[] args)
        {
            mytest1(5000);

            for (int i = 0; i < int.MaxValue; i++) { };
            
            mytest1(3000);

            Console.ReadLine();
        }

        static void mytest1(int senconds)
        {
            Console.WriteLine("mytest1 start...");
            Thread.Sleep(senconds);
            Console.WriteLine("mytest1 end...");
        }
    }

那如何用 perfview 来洞察呢?玩过 perfview 的朋友都知道它是带时间轴的,我们可以对上面的慢速方法 mytest1 适当的放大,一直找到那一次的慢速调用,为了能够记录到 Thread 使用 CPU 的情况,需要开启 ThreadTime 选项,截图如下:

完整的 Command 命令如下:


PerfView.exe  "/DataFile:PerfViewData.etl" /BufferSizeMB:256 /StackCompression /CircularMB:500 /KernelEvents:ThreadTime /ClrEvents:GC,Binder,Security,AppDomainResourceManagement,Contention,Exception,Threading,JITSymbols,Type,GCHeapSurvivalAndMovement,GCHeapAndTypeNames,Stack,ThreadTransfer,Codesymbols,Compilation /NoGui /NoNGenRundown /Merge:True /Zip:True collect

有了这些基础之后,先用 perfview 开启收集,然后执行应用程序,程序执行完成之后停止 perfview 收集,稍等片刻之后就有一个生成好的 zip 文件。

2. perfview 洞察

这里选择 Thread Time Stacks 视图,在弹框中选择我们的应用程序 ConsoleApp2,截图如下:

从卦象上看,当前的 ConsoleApp2 耗费了 3.2s 的CPU时间,总跟踪时间 17.19s

既然说了方法慢那必然是知道方法名的,只不过不知道慢在方法哪里,对应代码就是 mytest1() 方法,在 perfview 面板的 Find 输入框上搜索一下 mytest1 方法就可以找到,截图如下:

那这一行怎么解读呢? 我稍微说一下吧。

  • First:表示 mytest1 第一次被调用的时间戳
  • Last: 表示 myttest1 最后一次被释放的时间戳
  • when: 这里面是 32 个时间间隔的桶,每个桶的值是资源消化的比重。
  • TimeBucket: 一个桶的时间刻度,比如上图中的 633.8 ms

有了这些基础接下来就可以放大时间轴了,依次点击: First列 -> 右键菜单 -> Set Time Range ,放大后的截图如下:

When 列的 999999999999992________599999999 可以看到,当前这 11s 的挂钟时间内大概有两次 mytest1 调用,其实的 9 表示这个桶内消耗的单个资源的90%,我们要调查的就是其中 999999999999992 段,双击 When 列的 999999999999992 ,右键选择 Set Time Range 即可,截图如下:

放大到这里就差不多了,我们已经进入了第一次 mytest1 方法调用的作用域内,接下来依次点击 右键 -> Goto -> Goto Item in Callee 来观察下这个方法的下层到底都是写什么。

从卦中的 Inc 列来看,当前的 mytest1 方法耗费了 5.01s,其内部的 Thread.Sleep() 耗费了 5.005s ,这和测试代码中的 mytest1(5000); 不约而同。

哈哈,这不就找到了问题所在,在你的真实场景下,你可以继续观察底层的调用栈,找到问题所在。

三:总结

相信这篇能够给一些在慢速方法查找上有困惑的朋友找到一些灵感,还是那句话,CLR团队首推的 PerfView 在运行期监控方面是王者般的存在,与 WinDbg 优势互补。

图片名称

标签:洞察,C#,mytest1,PerfView,慢速,方法,perfview
From: https://www.cnblogs.com/huangxincheng/p/17571032.html

相关文章

  • 高效 API 接口对接淘宝天猫 1688 拼多多京东商品详情数据(H5 端,PC 端)
    api接口详解大全?优秀的设计是产品变得卓越的原因设计API意味着提供有效的接口,可以帮助API使用者更好地了解、使用和集成,同时帮助人们有效地维护它每个产品都需要使用手册,API也不例外在API领域,可以将设计视为服务器和客户端之间的协议进行建模API协议可以帮助内部和外部......
  • CentOS-Mysql 自动备份-shell 脚本
    功能说明:在服务器A上,每天自动运行一个shell脚本;备份数据库db;然后将sql文件放到另一台服务器B上。新建文件:mysql_backup.sh内容是:#!/bin/bashHOST=127.0.0.1USERNAME=rootPASSWORD=rootDBNAME=adverserverHost=123.123.123.123DATE=$(date+%Y%m%d)OLDDATE=$(date-d......
  • python3.6可以安装多少的torch、
    Python3.6可以安装多少的Torch?Torch是一个用于机器学习和深度学习的开源框架,其主要用于构建神经网络和进行大规模的数值计算。Torch提供了一个灵活而高效的工具集,使得开发者可以快速地构建和训练各种类型的神经网络模型。在Python中,我们可以使用Torch的Python包来使用......
  • docker下安装和使用jenkins
    docker-jenkins拉取项目dockerpulljenkins/jenkins:lts启动项目mkdir-p/usr/local/docker/jenkins_homechmod777/usr/local/docker/jenkins_homedockerrun-d-p10240:8080-p10241:50000-v/usr/local/docker/jenkins_home:/var/jenkins_home-v/etc/localti......
  • centos 6.2 64位安装nginx php mysql
    平台环境http://jiyunjie.blog.51cto.com/5348020/946860centos6.264位nginx-1.2.1php-5.3.14mysql-5.5.25阿里云2g内存实例,具体参数调整根据自己主机调整里面也提到一部分修改建议32位centos512内存参考http://jiyunjie.blog.51cto.com/5348020/907534 一、阿里云主机默认......
  • python3 excel写
    Python3Excel写入教程介绍在Python中,我们可以使用第三方库来实现Excel的读写操作。本文将向你介绍如何使用Python3来实现Excel写入的功能,帮助你入门并快速上手。整体流程下面是实现Python3Excel写入的整体流程,我们将使用openpyxl库来完成此任务。步骤动作代码1导......
  • Atcoder Regular Contest 124 E - Pass to Next
    首先第一步是一个浅显的观察:我们要求的是所有可能的最终序列的贡献之和,如果能改为计算所有操作序列的贡献之和那问题会简单很多,并且我们惊奇地发现,如果一组\(x_i\)全大于\(0\),那么把它们全减去\(1\)以后得到的答案序列不会改变,而对于任意一种可能的最终序列,必然存在一组\(\m......
  • JavaScript(一)
    简介:JavaScript不学不行啊,ajax,前端交互,都需要的。一:书写位置1.内部位置 2.外部位置3.行内一般在框架里支持二:注释1.单行注释//这里是注释  快捷键:ctrl+/2.多行注释/*这里是多行注释*/快捷键:alt+shift+a 三:结束符每行的结束符是“;”现在发展的可用可不......
  • python代码优化 编译cuda
    Python代码优化编译CUDAPython是一种高级编程语言,通常被用于快速开发和原型设计。然而,由于其动态类型和解释执行特性,Python在执行大规模计算密集型任务时可能会变得相对较慢。为了解决这个问题,我们可以使用CUDA编译Python代码。CUDA(ComputeUnifiedDeviceArchitecture)是一种由......
  • 值类型的侦听器watch不触发 immediate: true
    现象:一个组件的变量有初始值,然后,如果在引用该变量的页面onLoad中为组件的变量赋不同的新值,不触发对该变量的watch回调原因:onLoad的时候,组件还没有初始化完成,修改其变量的值相当于给它一个初始化的值,所以不会触发watch的回调。解决:watch里应该加上immediate:true,以便在创建侦听......