zoukankan      html  css  js  c++  java
  • 使用 Visual Studio 分析器找出应用程序瓶颈

    VS的性能分析工具

    性能分析工具的选择

    打开一个“性能分析”的会话:Debug->Start Diagnotic Tools Without Debugging(或按Alt+F2),VS2013在Analysis菜单中。 

    性能分析 
    性能分析

    CPU Usage

    检测CPU的性能,主要用于发现影响CPU瓶颈(消耗大量CPU资源)的代码。

    GPU Usage

    检测GPU的性能,常用于图形引擎的应用(如DirectX程序),主要用于判断是CPU还是GPU的瓶颈。

    Memory Usage

    检测应用程序的内存,发现内存。

    Performance Wizard

    性能(监测)向导,综合检测程序的性能瓶颈。这个比较常用,下面再逐一说明。

    性能(监测)向导

    1. 指定性能分析方法; 
      性能分析方法 
      性能分析方法

      CPU Sampling(CPU采样): 
      进行采样统计,以低开销水平监视占用大量CPU的应用程序。这个对于计算量大的程序可大大节省监控时间。 
      Instrumentation(检测): 
      完全统计,测量函数调用计数和用时 
      .NET memory allocation(.NET 内存分配): 
      跟踪托管内存分配。这个好像只有托管代码(如C#)才可用,一般以C++代码好像不行。 
      Resource contention data(并发): 
      检测等待其他线程的线程,多用于多线程的并发。
    2. 选择要检测的模块或应用程序;
    3. 启动分析程序进行监测。

    性能分析报告

    程序分析完成之后会生成一个分析报告,这就是我们需要的结果。 

    性能分析报告 
    性能分析报告概要

    视图类型

    有几个不同的视图可供我们切换,下面加粗的部分是个人觉得比较方便和常用的视图。 
    Summary(概要):整个报告概要说明 
    Call Tree(调用树):以树形表格的方式展开函数之间的关系。 
    Module(模块):分析调用的不同的程序模块,如不同的DLL、lib模块的耗时 
    Caller/Callee(调用与被调用):以数值显示的调用与被调用的关系 
    Functions(函数统计):以数值显示的各个函数的执行时间和执行次数统计值 
    Marks(标记): 
    Processers(进程): 
    Function Detials(函数详情):以图表的方式形象地显示:调用函数-当前函数-被调用子函数之间的关系和时间比例。 


    调用树 
    调用树 
    函数详情 
    函数详情 
    函数统计 
    函数统计 

    专用术语

    如果是第一次看这报告,你还不一定能看懂。你需要先了解一些专用术语(你可以对照着Call Tree视图和Functions视图去理解): 
    Num of Calls:(函数)调用次数 
    Elapsed Inclusive Time:已用非独占时间 
    Elapsed Exclusive Time:已用独占时间 
    Avg Elapsed Inclusive Time:平均已用非独占时间 
    Avg Elapsed Exclusive Time:平均已用独占时间 
    Module Name:模块名称,一般为可执行文件(.exe)、动态库(.dll)、静态库(.lib)的名称。

    也许看完你还迷糊,只要理解什么是独占与非独占你就都明白了。

    什么是独占与非独占

    非独占样本数是指的包括了子函数执行时间的总执行时间 
    独占样本数是不包括子函数执行时间的函数体执行时间,函数执行本身花费的时间,不包括子(函数)树执行的时间。

    解决应用案例问题

    我们已经大致了解了VS2015性能分析工具的使用方法。现在回归本质,解决上面提及的应用案例的问题。

    1、我们选择Function Detials视图,从根函数开始依据百分比最大的项选择,直到选择PrintPrimeSum,这时可以看到如下图: 

    找出性能瓶颈1 
    找出性能瓶颈1


    我们可以看到IO占了50%多(49.4%+9.7%)的时间,所以IO是最大的性能瓶颈。其实,有一定编程经验的人应该都能明白,在控制台输出信息是很耗时的。我们只是需要结果,不一定非要在控制中全部输出(这样还不便查看),我们可以将结果保存到文件,这样也比输出到控制台快。

    注:上图所示的时间,应该是非独占时间的百分比。

    知道了瓶颈,就改进行代码优化吧:

    void PrintPrimeSum()
    {
        int64_t startTime = GetSysTimeMicros();
        std::ofstream outfile;
        outfile.open("D:\Test\PrimeSum.dat", std::ios::out | std::ios::app);
        int count = 0;
        int64_t sum = 0;
        for (int i = 10000; i <= 100000; i++)
        {
            if (IsPrime(i))
            {
                sum = CalculateSum(i);
                outfile << sum << "	";
                count++;
                if (count % 10 == 0)
                {
                    outfile << std::endl;
                }
            }
        }
        outfile.close();
        int64_t usedTime = GetSysTimeMicros() - startTime;
        int second = usedTime / 1000000;
        int64_t temp = usedTime % 1000000;
        int millise = temp / 1000;
        int micros = temp % 1000;
        std::cout << "执行时间:" << second << "s " << millise << "' " << micros << "''" << std::endl;
    }

    再次执行,发现时间一下减小到:3s 798’ 218”。效果很明显!


    2、但这还不够,继续检查别的问题,对新代码再次用性能分析工具检测一下。 

    找出性能瓶颈2 
    找出性能瓶颈2

    我们发现IsPrime函数占用了62%的时间,这应该是一个瓶颈,我们能不能对其进行算法的优化?仔细想想,上面求质数的方法其实是最笨的方法,稍微对其进行优化一下:

    // 判断整数n是否为质数
    bool IsPrime(int n)
    {
        if (n < 2)
        {
            return false;
        }
    
        if (n == 2)
        {
            return true;
        }
    
        //把2的倍数剔除掉
        if (n%2 == 0)
        {
            return false;
        }
    
        // 其实不能被小于n的根以下的数整除,就是一个质数
        for (int i = 3; i*i <= n; i += 2)
        {
            if (n % i == 0)
            {
                return false;
            }
        }
    
        return true;
    }

    再次执行,发现时间一下减小到:1s 312’ 75”,几乎减了一半的时间。

    3、这还是有点慢,再看看还能不能进行优化。对新代码再次用性能分析工具检测一下。 

    找出性能瓶颈2 
    找出性能瓶颈2

    CalculateSum函数占了88.5%的时间,这绝对是影响目前程序性能的主要因素。对其进行。仔细想想,求1到N的和其实就是求1、2、3 … N的等差数列的和。优化代码如下:

    // 计算1到n之间所有整数的和
    int64_t CalculateSum(int n)
    {
        if (n < 0)
        {
            return -1;
        }
    
        //(n * (1 + n)) / 2
        return ( n * (1 + n) ) >> 1;
    }
    • 再次执行,发现时间一下减小到:0s 91’ 6”,一秒中之内,基本上可以满足要求子。

    总结

    程序性能调优,就是数上面这样一点点地改进的过程,直到满足应用的要求。上面只用了一个视图的一种统计指标(各函数所用时间占总时间的百分比),就解决了问题。对于大型的复杂应用程序,我们可以结果多种视图的多种统计指标进行综合判断,找出程序性能的瓶颈!

     

     

     

    使用 Visual Studio 分析器找出应用程序瓶颈

    Hari Pulapaka and Boris Vidolov

    本文讨论:

    以性能瓶颈为目标

    应用程序代码分析

    比较分析数据

    性能报告

    本文使用了以下技术: 

    Visual Studio 2008

    在过去十年间,涌现了许多新的软件技术和平台。每种新技术都要求掌握专门的知识才能创建出性能良好的应用程序。现在,由于各种 Internet 技术(如博客)使失望的用户可轻松地否定您的应用程序,因此您确实需要将性能放到首要位置。在计划早期,就应添加响应性能要求并创建原型来确定可能的技术限制。在整个开发过程中,还应衡量应用程序的各个性能方面以发现可能的性能下降,同时确保速度较慢情形下的测试人员文件并跟踪其错误。

    即使拥有最好的计划,仍必须在产品开发过程中调查性能问题。在本文中,我们将向您展示如何使用 Visual Studio® Team System Development Edition 或 VisualStudio Team Suite 来确定应用程序中的性能瓶颈。将通过演练一个示例性能调查来向您介绍 Visual Studio 分析器。请注意,尽管我们在本文中是使用 C# 来编写代码示例,但是此处的大部分示例对于本机 C/C++ 和 Visual Basic® 代码也同样有效。

     

    应用程序分析

    我们将使用先前提及的两个 Visual Studio 版本所附带的分析器。首先编写一个用于绘制 Mandelbrot 不规则图形的小型示例项目(如图 1 所示)。该应用程序不是非常有效,并且需要约 10 秒钟才能绘制出不规则图形。

    图-1 性能测试的目标程序

    要开始调查,从 Visual Studio 2008 的新“Analyze”(分析)菜单启动“Performance Wizard”(性能向导)。在 Visual Studio 2005 中,此功能可从“工具”|“性能工具”菜单获得。从而启动一个包含三个步骤的向导,其中第一步是指定目标项目或网站。第二步提供两种不同的分析方法:采样和检测。(有关这些分析方法的详细信息,请参阅“性能分析解释”侧栏。)现在,我们将选取默认值。

    向导完成后,显示一个“Performance Explorer”(性能资源管理器)对话框并创建一个新的性能会话。此会话包含目标应用程序(在我们的示例中为 Mandel)并且没有报告。要启动分析,单击工具窗口工具栏中的“Launch with Profiling”(启动并分析)按钮。

    应用程序绘制完不规则图形后,立即关闭窗体停止分析。Visual Studio 自动将一个新创建的报告添加到性能会话中并开始进行分析。分析完成后,Visual Studio 分析器会显示“Performance Report Summary”(性能报告摘要),列出开销最大的函数(请参见 图 2)。报告以两种方式显示这些函数。第一种方式衡量所列出函数直接或间接执行的工作。对于每个函数,数字代表在函数主体及其所有子调用中收集的积累样本。第二个列表不计算在子调用中收集的样本。此摘要页面显示 Visual Studio 分析器在执行 DrawMandel 方法期间收集了 30.71%的样本。剩余 69%的样本则分散在其他各个函数间,在此就不加赘述。要了解更多有关报告选项的信息,请参阅侧栏“报告可视化选项”。

    图-2 性能测试显示开销较大的函数调用

    请查看报告的“Call Tree”(调用树)视图(如图 3 所示),“Inclusive Samples %”(包含样本 %)列代表在函数及其子项中收集的样本。“Exclusive Samples %”(独占样本 %)列代表仅在函数主体中收集的样本。可看到 DrawMandel 方法直接调用 Bitmap.SetPixel。尽管 DrawMandel 自身占据了总样本的 30.71%,但 Visual Studio 分析器从 Bitmap.SetPixel 及其子项收集了 64.54%的样本。其中 Bitmap.SetPixel 主体仅占 0.68%(因此它并未显示在摘要页面上)。但是,Bitmap.SetPixel 通过其子项产生了大部分处理。它才是应用程序的真正瓶颈。

    图-3 被测应用程序的调用树示例

    显然地,Bitmap.SetPixel 对于 Mandel 项目而言并非最佳。我们的应用程序需要一种更快的方式来访问窗体上的所有像素。幸运的是,位图类还提供有另一个有用的 API:Bitmap.LockBits。此函数允许程序直接写入位图内存,从而减少了设置单个像素的开销。此外,为优化绘图,我们将创建一个纯整数数组并用每个像素的颜色值加以填充。随后,通过单个操作将该数组的值复制到位图中。

    优化应用程序

    性能分析解释

    使用采样方法 进行分析时,分析器以一种类似于调试程序的方式附加到正在运行的进程。然后,分析器会定期中断进程并检查哪个函数处于堆栈顶部以及该函数的代码路径。换句话说,Visual Studio 分析器收集当前进程状态的样本。采样是一种非入侵式统计型分析方法。在函数中收集的样本越多,函数可能执行的处理就越多。

    Visual Studio 分析器还会收集有关导致此执行的调用路径的信息。因此,此工具可在分析收集的数据后显示整个调用堆栈。默认情况下,Visual Studio 分析器每 1 千万个 CPU 周期收集一个样本。除 CPU 周期外,还可能在出现其他事件(如页面错误、系统调用、CPU 高速缓存缺失等等)时执行采样。分析会话的属性控制分析器的取样对象以及频率。

    作为一个低开销解决方案,采样常常是推荐选项。但值得注意的是,采样仅在程序有效使用 CPU 时收集信息。因此,当进程在等待磁盘、网络或任意其他资源时,Visual Studio 分析器均不会收集样本。这就是如果应用程序并未有效使用 CPU,建议使用检测分析的原因。

    在检测模式中,Visual Studio 分析器通过在每个函数的开头和结尾处注入特殊指令(称为探针)来修改(检测)二进制文件。探针允许分析器度量运行每个函数所花的时间。此外,分析器还会在每个外部函数调用周围添加一对探针,从而可确定这些外部调用的开销。

    通过使用检测分析,可准确测量各种数据,如运行函数所花时间(“经过的时间”)、函数的调用次数以及函数正在使用 CPU(“应用程序时间”)且未被 OS 切换出来的时间。检测的缺点是收集了大量数据,因而需要花费更长的分析时间。此外,此分析模式还具有更高的运行时开销。更高开销可能不经意间更改所分析应用程序的性能特征。

    通过同时使用采样和检测,还可收集基于 Microsoft® .NET Framework 的应用程序的内存分配数据。用户可使用性能会话属性页面启用和调整 .NET 内存分配数据的收集。它通常被称为内存分析,并且有大量关于该主题的 MSDN® 文档。请注意,它是分析器中唯一一个仅用于 .NET Framework 兼容代码的功能。对于其他功能,Visual Studio 分析器在本机 C/C++ 和基于 .NET 的应用程序之间完全相同。

    接下来修改 DrawMandel 方法以使用 LockBits 而非 SetPixel,并看看此更改会产生何种性能。创建位图后,添加以下代码行来锁定位图位并获得指向位图内存的指针:

    1. BitmapData bmpData =   
    2.     bitmap.LockBits(  
    3.         new Rectangle(0, 0, Width, Height),   
    4.         ImageLockMode.ReadWrite,   
    5.         bitmap.PixelFormat);  
    6. IntPtr ptr = bmpData.Scan0;  
    7. int pixels = bitmap.Width * bitmap.Height;  
    8. Int32[] rgbValues = new Int32[pixels];  


    然后,在设置像素的内部循环中,注释掉对 Bitmap.SetPixel 的调用并用新语句加以替换,具体如下:

    1. //bitmap.SetPixel(column, row, colors[color]);  
    2. rgbValues[row * Width + column] =   
    3.     colors[color].ToArgb();  

    此外,添加以下代码行来将数组复制到位图内存中:

    1. Marshal.Copy(rgbValues, 0, ptr, pixels);  
    2. bitmap.UnlockBits(bmpData);  

    现在,如果重新在分析器中运行应用程序,可以看到不规则图形的绘制速度几乎快了三倍(请参见图 4)。请注意,新性能报告的摘要页面显示 DrawMandel 的主体直接占据了总样本的 83.66%。由于我们优化了绘图,瓶颈现在变成了不规则图形的计算。

    图-4 修订代码的性能分析

    现在,我们将更进一步优化该计算。遗憾的是,此次需要查找单个函数中的瓶颈。DrawMandel 是一个比较复杂的方法,因而很难知道应关注哪些计算。幸运的是,Visual Studio 2008 采样分析器还默认收集行级数据,从而有助于确定函数中的哪些行开销最大。

    要查看行级数据,需从其他角度查看性能报告。从“Current View”(当前视图)菜单切换到“Modules”(模块)视图。与“Call Tree”(调用树)视图不同,“Modules”(模块)视图不会显示在父函数上下文中各函数的相互调用方式以及这些调用的开销等信息。相反,“Modules”(模块)视图包含每个可执行文件(程序集或 DLL)以及该可执行文件中每个函数的累积总样本数。Visual Studio 分析器从所有调用堆栈累积该数据。

    “Modules”(模块)视图比较适合于观察更大的图片。例如,如果按“Exclusive Samples %”(独占样本 %)列排序,可以看到 Mandel.exe 自身执行 87.57%的处理。作为优化后的结果,GDI+ 占用不到 3%的处理。展开这些模块,可以看到单个方法的相同信息。此外,在 Visual Studio 2008 中,除函数级以外,还可展开树来查看单个行甚至这些行中单个指令的相同数据(请参见图 5)。

    Figure 5 跳到分析的代码行

    跳到源代码可查看如图 6 所示的代码。代码在最内部循环中计算平方根。此操作开销很大且占用 18% 的总应用程序处理。图 6 中突出显示的行显示了可优化的代码。第一行使用了一个不必要的平方根,而第二行对于 while 循环是不变的。

    原始代码

    1. for (int column = 1; column < Width; column++)  
    2. {  
    3.  y = yStart;  
    4.  for (int row = 1; row < Height; row++)  
    5.  {  
    6.   double x1 = 0;  
    7.   double y1 = 0;  
    8.   int color = 0;  
    9.   int dept = 0;  
    10.   while (dept < 100 && Math.Sqrt((x1 * x1) + (y1 * y1)) < 2)  
    11.   {  
    12.    dept++;  
    13.    double temp = (x1 * x1) - (y1 * y1) + x;  
    14.    y1 = 2 * x1 * y1 + y;  
    15.    x1 = temp;  
    16.    double percentFactor = dept / (100.0);  
    17.    color = ((int)(percentFactor * 255));  
    18.   }  
    19.   //Comment this line to avoid calling Bitmap.SetPixel:  
    20.   //bitmap.SetPixel(column, row, colors[color]);  
    21.   //Uncomment the block below to avoid Bitmap.SetPixel:  
    22.   rgbValues[row * Width + column] = colors[color].ToArgb();  
    23.   
    24.   y += deltaY;  
    25.  }  
    26.  x += deltaX;  
    27. }  

    优化后的代码

    1. for (int column = 1; column < this.Width; ++column)  
    2. {  
    3.  y = yStart;  
    4.  int index = column;  
    5.  for (int row = 1; row < Height; row++)  
    6.  {  
    7.   double x1 = 0;  
    8.   double y1 = 0;  
    9.   int dept = 0;  
    10.   double x1Sqr, y1Sqr;  
    11.   while (dept < 100 && ((x1Sqr = x1 * x1) + (y1Sqr = y1 * y1)) < 4)  
    12.   {  
    13.    dept++;  
    14.    double temp = x1Sqr - y1Sqr + x;  
    15.    y1 = 2 * x1 * y1 + y;  
    16.    x1 = temp;  
    17.   }  
    18.   rgbValues[index] = colors[((int)(dept * 2.55))].ToArgb();  
    19.   index += Width;  
    20.   
    21.   y += deltaY;  
    22.  }  
    23.  x += deltaX;  
    24. }    

    修改后,重新分析应用程序并检查优化后代码的性能。生成和运行应用程序后,现在在 1-2 秒内就能重新绘制不规则图形。因而显著减少了应用程序的启动时间。

    Visual Studio 2008 包含一个可比较两个性能报告的新功能。为实际了解此功能,我们在分析器中重新运行应用程序并捕获最新的性能报告。要查看两个应用程序版本之间的差异,在“Performance Explorer”(性能资源管理器)中选择原始报告和最新报告。右键单击报告,并单击上下文菜单中的“Compare Performance Reports”(比较性能报告)选项。此命令将生成一个新的报告,显示所有函数以及两个报告中的该函数的“Exclusive Samples %”(独占样本 %)值之间的差异。由于我们削减了总体执行时间,所以 DrawMandel 的相对百分比从 31.76 上升到 70.46。

    为更好地查看实际优化效果,将比较选项窗格中的列更改为“Inclusive Samples”(包含样本)(请参见图 7)。同时将阈值增加到 1500 个样本以忽略微小的波动。此外,您可能已注意到:在默认情况下,报告显示负数或首先显示优化最少的函数(因为它常用于查找性能下降)。但是,出于优化目的,我们将反向排序 Delta 列,以便可以在顶部看到最优化的函数。请注意,DrawMandel 及其子函数的样本数从 2,064 变为 175。超过了十倍的优化!为展示所取得的性能改进,可复制并粘贴该报告的任何部分。

    图-7 比较 DrawMandel的优化结果 

    目标分析

    报告可视化选项

    Visual Studio 可 使用以下各种性能报告选项以多种方式查看性能数据:“Call Tree”(调用树)、“Modules”(模块)、“Functions”(函数)以及其他选项。打开报告时默认显示“Summary”(摘要)视图。例如,要在 Visual Studio 2008 中查找产生大多数处理的调用路径,请从“Current View”(当前视图)菜单选择“Call Tree”(调用树)视图。(在 Visual Studio 2005 中,在报告底部选择“调用树”选项卡。)“Call Tree”(调用树)视图包含所有调用堆栈的聚合树。“Inclusive Samples %”(包含样本 %)列显示这些代码路径中每个分支的总开销。沿着开销最大的分支,就可以找到性能瓶颈。

    在 Visual Studio 2008 中,分析器团队添加了两个新的功能来简化性能报告的使用。添加的第一个功能是降噪选项。默认情况下,报告现在会裁掉不重要的小函数,从而使用户能很容易地查看具有更大影响的函数。此选项通常称为剪裁。另外,团队通过将自身不进行任何处理而只调用其他函数进行处理的函数放到一起,从而减少了调用树的深度。Visual Studio 分析器将其称为折叠。

    性能报告中的降噪选项控制剪裁和折叠的阈值。如果在性能报告中查找特定函数时遇到问题,则可关闭降噪选项。

    对 Visual Studio 2008 中调用树的第二个较大的改进是“Hot Path”(热路径)按钮和相应上下文菜单。“热路径”会突出显示程序中开销最大的代码路径,并沿着该路径向下直至看到单个函数所执行(并且不是委派)的重大处理。然后,“热路径”会突出显示该函数。如果有两个或多个单独的重要代码路径,则“热路径”将停在树中出现分支的位置。如果“热路径”为应用程序提供了多个分支,则可选择最感兴趣的一个,并对该特定分支重新应用“热路径”。

    --------------------

    Visual Studio 2017 RC的最新文档,请参看https://docs.microsoft.com/zh-cn/visualstudio/.

    你可以使用Visual Studio Profiling工具来分析你的应用程序中的性能问题。本文展示了如何使用采样数据。

    采样是一种统计学习方法,可以向你展示:在应用中,那一部分做了绝大多数的用户模型工作。采样是一个很好的方式用来寻找从哪里可以加速你的程序。

    在指定的时间间隔,采样方法收集在应用程序中执行的函数的信息。当你完成一个分析的运行后,被分析的数据的摘要视图展示了最活跃的函数,称之为Hot Path,应用程序中的大多数的工作被执行。视图还列出了执行功能的最独特的工作,并且提供了一个时间线的图表,你可以使用这个图标只考虑其中一部分的抽样结果。

    如果采样的方法不能给你你想要的结果,其他的分析工具收集方法能够提供不同的信息,可能对你有帮助,关于这些方法的更多信息请参看 https://msdn.microsoft.com/en-us/library/ms182374.aspx

    小贴士:

    如果你的配置文件的代码调用Windows函数,你应该确保你有最新的PDB文件。没有这些文件,你的报告视图将会列出Windows函数的名字,它们往往很神秘并且很难理解的。关于更多的如何确保你有你需要的文件的信息请参考:https://msdn.microsoft.com/en-us/library/89axdy6y.aspx

    创建并且运行一个性能会话

    为了得到你需要分析的数据,你必须首先创建一个性能会话,然后运行这个会话,性能向导可以使你两者兼顾。

    如果你不是分析一个Windows桌面应用程序或asp.NET应用程序,你必须使用其他的某一种分析工具,参看 https://msdn.microsoft.com/en-us/library/mt210448.aspx.

    步骤一:为了创建并且运行一个性能会话:

    1.在VS中打开解决方案,设置配置为Release。(在工具栏中找到“解决方案配置”,把Debug改成Release)

    注意:如果你不是你正在使用的这台电脑的管理员,当你使用profiler的时候你应该以管理员的身份运行VS。(右击VS的运行图标,然后点击“以管理员身份运行”)

    2.在“调试”菜单中,单击“性能分析器”

    3.单击“性能向导”选项,并单击“开始”

    4.单击“CPU采样”选项,单击“完成”

    5.你的应用程序启动,并且分析器开始收集数据

    6.操作功能可能包含性能问题

    7.如你通常所做的,关闭应用程序

    当你运行完成这个应用后,被分析数据的摘要视图出现在VS的主窗口中,新的会话图标出现在性能探测器窗口。

    步骤二:分析采样数据

    当你完成一个性能会话时,分析报告的摘要视图出现在VS的主窗口中。

    我们建议你从检查Hot Path开始分析你的数据,函数列表就是做的绝大多数的工作,最后通过使用摘要时间表分析其他函数。你可以查看配置建议和错误列表中的警告。

    请注意,抽样方法可能不能给你你所需要的信息。例如,只有当应用程序正在执行用户模式代码时采样才会被收集。因此,一些功能,例如输入和输出操作,是不能被采样的。分析工具提供了一些方法的集合,能够使你专注分析一些重要的数据。有关其他方法的更多信息请参看https://msdn.microsoft.com/enus/library/ms182374.aspx.

    图中的每一个标号区域对应一个过程的步骤:

    为了分析采样数据:

    1.在摘要视图中,Hot Path展示了你的应用程序中具有最高包容样本的分支。当数据被收集时,这是最活跃的执行路径。高包容值可以表明该算法生成的调用树可以优化。发现代码中的函数中的最短路径,注意,路径可以包括系统功能和在外部模块中的系统功能。

    (1)Inclusive Samples:表明函数做了多少工作,以及哪些函数调用它。高包容性计数指向函数最昂贵的整体。

    (2)Exclusive Samples:表示多少工作是由函数体中的代码做的,不包括调用它的函数做的工作。高独家计数表示函数本身的性能瓶颈。

    2.单击函数名称来显示分析数据的功能细节视图。功能细节视图提供了一个分析数据的图形化视图选择功能,显示该函数调用的所有函数以及调用该函数的所有函数。

    调用函数和被调用函数的块的大小表示函数调用的相对频率。

    你可以单击调用函数或被调用函数的名称,使其显示所选函数的函数细节。

    较低的平面的功能细节窗口显示功能代码本身。如果你检查代码发现一个优化其性能的机会,单击原文件的名字,从而在VS的编辑器中打开该文件。

    3. 继续你的分析,通过在视图的下拉列表中选择 Summary回到摘要视图。然后在Functions Doing the Most Individual Work中检查函数。这个列表显示具有最高独家样本的函数。这些函数中的函数体的代码执行重要工作,你可以对其进行优化。为了进一步分析一个特定的功能,单击函数的细节视图来显示它。

    继续你的调查分析,你可以重新分析被分析数据的一段,通过使用摘要视图中的时间线,向你展示被选择部分的Hot Path和Functions Doing Most Individual Work,关注于时间线上的一个小的峰值,这可能会揭示出昂贵的调用树和函数,这些内容在整个分析运行中可能没有显示。

    为了重新分析一小段,在时间线中选择一小段,然后单击Filter by Selection。

    4.分析器还使用一套规则提出改善分析运行的方式,并确定可能的性能问题。如果找到一个问题,在错误列表中就会显示一个警告窗口。

    视图菜单上单击错误列表,然后打开错误列表窗口。

    为了看到这个有错误的函数,提出了一个警告功能的细节视图中,双击警告。

    为了查看详细信息警告,右击错误,然后单击显示错误帮助

    步骤三:修改代码并重新运行会话

    在你发现有一个或多个功能可以进行优化时,你可以重复运行分析并比较数据的差异,从而得到你更改后的应用程序的性能。

    修改代码并重新运行分析器

    1.修改你的代码

    2.为了打开Performance Explorer。在Debug菜单中单击“Profiler”,然后单击“ Performance Explorer ”,然后单击“Show Performance Explorer”

    3.在Show Performance Explorer中,右击你想运行的会话,然后单击“启动与剖析”

    4.你重新运行一个会话以后,另一个数据文件就会被添加到报告文件夹中,选择原始的分析数据和新的分析数据,右击选择,然后单击“比较性能报告”

    一份新的报告在窗口中打开,显示比较结果。关于如何使用比较视图的更多信息,参看:https://msdn.microsoft.com/en-us/library/bb38575

  • 相关阅读:
    scala 基础
    Feign拦截器和解码器
    SpringCloud对使用者透明的数据同步组件
    POI SXSSF API 导出1000万数据示例
    HDFS文件浏览页返回上级目录功能
    Spring Security OAuth2.0
    Spring Security实现OAuth2.0授权服务
    Spring Security实现OAuth2.0授权服务
    Zookeeper学习笔记:简单注册中心
    Eclipse集成Git做团队开发:分支管理
  • 原文地址:https://www.cnblogs.com/liangqihui/p/7275368.html
Copyright © 2011-2022 走看看