利用VisualStudio分析器找出应用程序瓶颈.docx
- 文档编号:9597370
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:15
- 大小:425.94KB
利用VisualStudio分析器找出应用程序瓶颈.docx
《利用VisualStudio分析器找出应用程序瓶颈.docx》由会员分享,可在线阅读,更多相关《利用VisualStudio分析器找出应用程序瓶颈.docx(15页珍藏版)》请在冰点文库上搜索。
利用VisualStudio分析器找出应用程序瓶颈
利用VisualStudio分析器找出应用程序瓶颈
在过去十年间,涌现了许多新的软件技术和平台。
每种新技术都要求把握专门的知识才能创建出性能良好的应用程序。
此刻,由于各类Internet技术(如博客)使失望的用户可轻松地否定您的应用程序,因此您确实需要将性能放到首要位置。
在打算初期,就应添加响应性能要求并创建原型来确信可能的技术限制。
在整个开发进程中,还应衡量应用程序的各个性能方面以发觉可能的性能下降,同时确保速度较慢情形下的测试人员文件并跟踪其错误。
即便拥有最好的打算,仍必需在产品开发进程中调查性能问题。
在本文中,咱们将向您展现如何利用VisualStudio® TeamSystemDevelopmentEdition或VisualStudioTeamSuite来确信应用程序中的性能瓶颈。
将通过演练一个例如性能调查来向您介绍VisualStudio分析器。
请注意,尽管咱们在本文中是利用C#来编写代码例如,可是此处的大部份例如关于本机C/C++和VisualBasic® 代码也一样有效。
应用程序分析
咱们将利用先前提及的两个VisualStudio版本所附带的分析器。
第一编写一个用于绘制Mandelbrot不规那么图形的小型例如项目(如图1 所示)。
该应用程序不是超级有效,而且需要约10秒钟才能绘制出不规那么图形。
Figure1 性能测试的目标程序 (单击该图像取得较大视图)
要开始调查,从VisualStudio2020的新“Analyze”(分析)菜单启动“PerformanceWizard”(性能向导)。
在VisualStudio2005中,此功能可从“工具”|“性能工具”菜单取得。
从而启动一个包括三个步骤的向导,其中第一步是指定目标项目或网站。
第二步提供两种不同的分析方式:
采样和检测。
(有关这些分析方式的详细信息,请参阅“性能分析说明”侧栏。
)此刻,咱们将选取默许值。
向导完成后,显示一个“PerformanceExplorer”(性能资源治理器)对话框并创建一个新的性能会话。
此会话包括目标应用程序(在咱们的例如中为Mandel)而且没有报告。
要启动分析,单击工具窗口工具栏中的“LaunchwithProfiling”(启动并分析)按钮。
应用程序绘制完不规那么图形后,当即关闭窗体停止分析。
VisualStudio自动将一个新创建的报告添加到性能会话中并开始进行分析。
分析完成后,VisualStudio分析器会显示“PerformanceReportSummary”(性能报告摘要),列出开销最大的函数(请参见 图2)。
报告以两种方式显示这些函数。
第一种方式衡量所列出函数直接或间接执行的工作。
关于每一个函数,数字代表在函数主体及其所有子挪用中搜集的积存样本。
第二个列表不计算在子挪用中搜集的样本。
此摘要页面显示VisualStudio分析器在执行DrawMandel方式期间搜集了30.71%的样本。
剩余69%的样本那么分散在其他各个函数间,在此就不加赘述。
要了解更多有关报告选项的信息,请参阅侧栏“报告可视化选项”。
Figure2 性能测试显示开销较大的函数挪用 (单击该图像取得较大视图)
请查看报告的“CallTree”(挪用树)视图(如图3 所示),“InclusiveSamples%”(包括样本%)列代表在函数及其子项中搜集的样本。
“ExclusiveSamples%”(独占样本%)列代表仅在函数主体中搜集的样本。
可看到DrawMandel方式直接挪用Bitmap.SetPixel。
尽管DrawMandel自身占据了总样本的30.71%,但VisualStudio分析器从Bitmap.SetPixel及其子项搜集了64.54%的样本。
其中Bitmap.SetPixel主体仅占0.68%(因此它并未显示在摘要页面上)。
可是,Bitmap.SetPixel通过其子项产生了大部份处置。
它才是应用程序的真正瓶颈。
Figure3 被测应用程序的挪用树例如 (单击该图像取得较大视图)
显然地,Bitmap.SetPixel关于Mandel项目而言并非最正确。
咱们的应用程序需要一种更快的方式来访问窗体上的所有像素。
幸运的是,位图类还提供有另一个有效的API:
Bitmap.LockBits。
此函数许诺程序直接写入位图内存,从而减少了设置单个像素的开销。
另外,为优化画图,咱们将创建一个纯整数数组并用每一个像素的颜色值加以填充。
随后,通过单个操作将该数组的值复制到位图中。
优化应用程序
性能分析说明
利用采样方式 进行分析时,分析器以一种类似于调试程序的方式附加到正在运行的进程。
然后,分析器会按期中断进程并检查哪个函数处于堆栈顶部和该函数的代码途径。
换句话说,VisualStudio分析器搜集当前进程状态的样本。
采样是一种非入侵式统计型分析方式。
在函数中搜集的样本越多,b31.org函数可能执行的处置就越多。
VisualStudio分析器还会搜集有关致使此执行的挪用途径的信息。
因此,此工具可在分析搜集的数据后显示整个挪用堆栈。
默许情形下,VisualStudio分析器每1万万个CPU周期收集一个样本。
除CPU周期外,还可能在显现其他事件(如页面错误、系统挪用、CPU高速缓存缺失等等)时执行采样。
分析会话的属性操纵分析器的取样对象和频率。
作为一个低开销解决方案,采样常常是推荐选项。
但值得注意的是,采样仅在程序有效利用CPU时搜集信息。
因此,当进程在等待磁盘、网络或任意其他资源时,VisualStudio分析器均可不能搜集样本。
这确实是若是应用程序并未有效利用CPU,建议利用检测分析的缘故。
在检测模式中,VisualStudio分析器通过在每一个函数的开头和结尾处注入特殊指令(称为探针)来修改(检测)二进制文件。
探针许诺分析器气宇运行每一个函数所花的时刻。
另外,分析器还会在每一个外部函数挪用周围添加一对探针,从而可确信这些外部挪用的开销。
通过利用检测分析,可准确测量各类数据,如运行函数所花时刻(“通过的时刻”)、函数的挪用次数和函数正在利用CPU(“应用程序时刻”)且未被OS切换出来的时刻。
检测的缺点是搜集了大量数据,因此需要花费更长的分析时刻。
另外,此分析模式还具有更高的运行时开销。
更高开销可能不经意间更改所分析应用程序的性能特点。
通过同时利用采样和检测,还可搜集基于Microsoft® .NETFramework的应用程序的内存分派数据。
用户可利用性能会话属性页面启用和调整.NET内存分派数据的搜集。
它通常被称为内存分析,而且有大量关于该主题的MSDN® 文档。
请注意,它是分析器中唯一一个仅用于.NETFramework兼容代码的功能。
关于其他功能,VisualStudio分析器在本机C/C++和基于.NET的应用程序之间完全相同。
接下来修改DrawMandel方式以利用LockBits而非SetPixel,并看看此更改会产生何种性能。
创建位图后,添加以下代码行来锁定位图位并取得指向位图内存的指针:
复制代码
BitmapDatabmpData=
bitmap.LockBits(
newRectangle(0,0,Width,Height),
ImageLockMode.ReadWrite,
bitmap.PixelFormat);
IntPtrptr=bmpData.Scan0;
intpixels=bitmap.Width*bitmap.Height;
Int32[]rgbValues=newInt32[pixels];
然后,在设置像素的内部循环中,注释掉对Bitmap.SetPixel的挪用并用新语句加以替换,具体如下:
复制代码
//bitmap.SetPixel(column,row,colors[color]);
rgbValues[row*Width+column]=
colors[color].ToArgb();
另外,添加以下代码行来将数组复制到位图内存中:
复制代码
Marshal.Copy(rgbValues,0,ptr,pixels);
bitmap.UnlockBits(bmpData);
此刻,若是从头在分析器中运行应用程序,能够看到不规那么图形的绘制速度几乎快了三倍(请参见图4)。
请注意,66bb.org新性能报告的摘要页面显示DrawMandel的主体直接占据了总样本的83.66%。
由于咱们优化了画图,瓶颈此刻变成了不规那么图形的计算。
Figure4 修订代码的性能分析 (单击该图像取得较大视图)
此刻,咱们将更进一步优化该计算。
遗憾的是,这次需要查找单个函数中的瓶颈。
DrawMandel是一个比较复杂的方式,因此很难明白应关注哪些计算。
幸运的是,VisualStudio2020采样分析器还默许搜集行级数据,从而有助于确信函数中的哪些行开销最大。
要查看行级数据,需从其他角度查看性能报告。
从“CurrentView”(当前视图)菜单切换到“Modules”(模块)视图。
与“CallTree”(挪用树)视图不同,“Modules”(模块)视图可不能显示在父函数上下文中各函数的彼此挪用方式和这些挪用的开销等信息。
相反,“Modules”(模块)视图包括每一个可执行文件(程序集或DLL)和该可执行文件中每一个函数的积存总样本数。
VisualStudio分析器从所有挪用堆栈积存该数据。
“Modules”(模块)视图比较适合于观看更大的图片。
例如,若是按“ExclusiveSamples%”(独占样本%)列排序,能够看到Mandel.exe自身执行87.57%的处置。
作为优化后的结果,GDI+占用不到3%的处置。
展开这些模块,能够看到单个方式的相同信息。
另外,在VisualStudio2020中,除函数级之外,还可展开树来查看单个行乃至这些行中单个指令的相同数据(请参见图5)。
Figure5 跳到分析的代码行 (单击该图像取得较大视图)
跳到源代码可查看如图6 所示的代码。
代码在最内部循环中计算平方根。
此操作开销专门大且占用18%的总应用程序处置。
图6 中突出显示的行显示了可优化的代码。
第一行利用了一个没必要要的平方根,而第二行关于while循环是不变的。
Figure 6 Code-LevelOptimizations
原始代码
复制代码
for(intcolumn=1;column { y=yStart; for(introw=1;row { doublex1=0; doubley1=0; intcolor=0; intdept=0; while(dept<100&&Math.Sqrt((x1*x1)+(y1*y1))<2) { dept++; doubletemp=(x1*x1)-(y1*y1)+x; y1=2*x1*y1+y; x1=temp; doublepercentFactor=dept/(100.0); color=((int)(percentFactor*255)); } //CommentthislinetoavoidcallingBitmap.SetPixel: //bitmap.SetPixel(column,row,colors[color]); //UncommenttheblockbelowtoavoidBitmap.SetPixel: rgbValues[row*Width+column]=colors[color].ToArgb(); y+=deltaY; } x+=deltaX; } 优化后的代码 复制代码 for(intcolumn=1;column { y=yStart; intindex=column; for(introw=1;row { doublex1=0; doubley1=0; intdept=0; doublex1Sqr,y1Sqr; while(dept<100&&((x1Sqr=x1*x1)+(y1Sqr=y1*y1))<4) { dept++; doubletemp=x1Sqr-y1Sqr+x; y1=2*x1*y1+y; x1=temp; } rgbValues[index]=colors[((int)(dept*2.55))].ToArgb(); index+=Width; y+=deltaY; } x+=deltaX; } 修改后,从头分析应用程序并检查优化后代码的性能。 生成和运行应用程序后,此刻在1-2秒内就能够从头绘制不规那么图形。 因此显著减少了应用程序的启动时刻。 VisualStudio2020包括一个可比较两个性能报告的新功能。 为实际了解此功能,咱们在分析器中从头运行应用程序并捕捉最新的性能报告。 要查看两个应用程序版本之间的不同,在“PerformanceExplorer”(性能资源治理器)当选择原始报告和最新报告。 右键单击报告,并单击上下文菜单中的“ComparePerformanceReports”(比较性能报告)选项。 此命令将生成一个新的报告,显示所有函数和两个报告中的该函数的“ExclusiveSamples%”(独占样本%)值之间的不同。 由于咱们削减了整体执行时刻,因此DrawMandel的相对百分比从31.76上升到70.46。 为更好地查看实际优化成效,将比较选项窗格中的列更改成“InclusiveSamples”(包括样本)(请参见图7)。 同时将阈值增加到1500个样本以忽略微小的波动。 另外,您可能已注意到: 在默许情形下,报告显示负数或第一显示优化最少的函数(因为它经常使用于查找性能下降)。 可是,出于优化目的,咱们将反向排序Delta列,以即能够在顶部看到最优化的函数。 请注意,DrawMandel及其子函数的样本数从2,064变成175。 超过了十倍的优化! 为展现所取得的性能改良,可复制并粘贴该报告的任何部份。 Figure7 比较DrawMandel的优化结果 (单击该图像取得较大视图) 目标分析 报告可视化选项 VisualStudio可 利用以下各类性能报告选项以多种方式查看性能数据: “CallTree”(挪用树)、“Modules”(模块)、“Functions”(函数)和其他选项。 打开报告时默许显示“Summary”(摘要)视图。 例如,要在VisualStudio2020中查找产生大多数处置的挪用途径,请从“CurrentView”(当前视图)菜单项选择择“CallTree”(挪用树)视图。 (在VisualStudio2005中,在报告底部选择“挪用树”选项卡。 )“CallTree”(挪用树)视图包括所有挪用堆栈的聚合树。 “InclusiveSamples%”(包括样本%)列显示这些代码途径中每一个分支的总开销。 沿着开销最大的分支,就能够够找到性能瓶颈。 在VisualStudio2020中,分析器团队添加了两个新的功能来简化性能报告的利用。 添加的第一个功能是降噪选项。 默许情形下,报告此刻会裁掉不重要的小函数,从而利用户能很容易地查看具有更大阻碍的函数。 此选项通常称为剪裁。 另外,团队通过将自身不进行任何处置而只挪用其他函数进行处置的函数放到一路,从而减少了挪用树的深度。 VisualStudio分析器将其称为折叠。 性能报告中的降噪选项操纵剪裁和折叠的阈值。 若是在性能报告中查找特定函数时碰到问题,那么可关闭降噪选项。 对VisualStudio2020中挪用树的第二个较大的改良是“HotPath”(热途径)按钮和相应上下文菜单。 “热途径”会突出显示程序中开销最大的代码途径,并沿着该途径向下直至看到单个函数所执行(而且不是委派)的重大处置。 然后,“热途径”会突出显示该函数。 若是有两个或多个单独的重要代码途径,那么“热途径”将停在树中显现分支的位置。 若是“热途径”为应用程序提供了多个分支,那么可选择最感爱好的一个,并对该特定分支从头应用“热途径”。 到目前为止,咱们已演示了如何利用VisualStudio分析器来改善应用程序的性能。 可是,许多实际应用程序都需要执行多个用户操作才能了解性能问题。 通常,您可能宁愿忽略在开始分析前搜集的所有数据。 另外,可能希望在单次运行中从多种情形搜集数据。 为演示如何针对此类情形利用分析器,咱们将切换话题并分析一个例如电子商务网站(事实上,咱们利用的是一个修改版本的TheBeerHouse例如,可从 依照本文目的,咱们将仅展现对第一种情形的调查。 可是,咱们将针对这两种情形搜集数据,并向您展现如何挑选数据以重点关注特定情形的性能问题。 第一,创建一个新的分析会话。 如前所述,通过“Analyze”(分析)菜单启动“PerformanceWizard”(性能向导),然后通过向导页面选择默许值。 请注意,关于网站,“InstrumentationProfiling”(检测分析)是默许选项。 网站一样不受CPU限制,通常依托数据库效劳器应用程序来承担繁重的任务。 因此,检测是更好的选项。 创建性能会话后,在分析器中启动网站,可是咱们将幸免启动时刻而且一次仅关注一种情形。 为此,在VisualStudio2020的“PerformanceExplorer”(性能资源治理器)中,可利用“LaunchwithProfilingPaused”(启动并暂停分析)选项来启动附加有VisualStudio分析器的应用程序,可是分析器在用户恢复分析之前可不能搜集任何数据(请参见图8)。 Figure8 启动时暂停分析器 当网站正在加载时,切换回VisualStudio。 请注意,VisualStudio分析器显示一个名为“DataCollectionControl”(数据搜集操纵)的新工具窗口。 此窗口许诺您多次暂停和恢复搜集。 该操纵的一个重要部份是预概念标记列表。 它们是可插入分析数据来指出感爱好的时刻点的书签或标签。 咱们利用这些标记来分隔每一个用户情形的开头和结尾。 第一,利用上下文菜单中的“RenameMark”(重命名标记)命令来重命名四个标记。 并删除未利用的标记(请参见图9)。 到目前为止,咱们已暂停分析以幸免启动时刻搜集并预备咱们的情形。 网站加载完毕后,恢复分析。 Figure9 为测试情形命名分析标记 咱们已做好开始第一个情形的预备。 通过选择ProductCatalogRequest标记并单击“InsertMark”(插入标记)按钮,标记该情形的开头。 然后切换回InternetExplorer®,通过显示产品目录完成第一个情形。 网站显示产品目录后,插入ProductCatalogRendered标记来指明此情形的结尾。 要转换到下一个情形,选择Beercap产品。 再次在添加前后插入各自的标记。 现在即完成所有情形,然后退出应用程序。 完成数据分析后,VisualStudio分析器显示“PerformanceReportSummary”(性能报告摘要)。 此报告与采样报告稍有不同,因为它显示的是挪用次数最多的函数和时刻最长函数的持续时刻。 值得注意的是,此数据是在整个应用程序的生存期聚合的,而且包括以上两个情形和所有之前的活动。 显然,咱们希望性能报告只向咱们显示给定情形的数据,而且挑选出其余部份。 在VisualStudio2020中,分析器具有一个新的“Marks”(标记)视图可列出所有插入的标记。 (请注意,VisualStudio分析器将其他自动标记插入程序的开头和结尾)。 要为第一个情形创建挑选器,选择说明该情形开头和结尾的标记,然后在上下文菜单当选择“AddFilteronMarks”(针对标记添加挑选器)。 从而自动创建所需的挑选器(请参见图10)。 除标记外,也可按线程、进程或时刻距离进行挑选。 设置挑选器后,可继续执行它。 Figure10 性能测试的目标程序 (单击该图像取得较大视图) 请注意,此挑选适用于性能报告中的所有视图。 这也是VisualStudio分析器自动显示已挑选数据的新摘要页面的缘故。 此摘要页面特定于产品目录呈现情形。 例如,能够看到System.IDisposable.Dispose花了3.4秒或61%的情形执行时刻,而之前需要41%。 通过挑选,咱们能够准确地看出此函数关于特定问题的重要程度。 此刻修复此性能问题。 需在代码中找处处置这些对象的函数。 最简单的方式是利用“挪用树”和“热途径”功能(如图11 所示)。 它会当即显示是SetInputControlsHighlight函数引发对IDisposable.Dispose的大多数挪用。 Figure11 利用热途径查找问题 (单击该图像取得较大视图) 事实证明该函数包括一个效率很低的日记记录机制: 复制代码 foreach(Controlctlincontainer.Controls){ log+="Settingupcontrol: "+ctl.ClientID; stringtempDir= Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); using(StreamWritersw=newStreamWriter( Path.Combine(tempDir,"WebSite.log"),true)){ sw.WriteLine(log); } ... 它是在调试进程中错误留下的大量日记而且再也不用于任何特定诊断目的,因此能够安心地将其删除。 一样,VisualStudio2020中的“热途径”功能可让咱们快速确信应用程序中的瓶颈。 不管您是用本机C/C++、C#仍是VisualBasic来编写应用程序,VisualStudio分析器都能显著简化性能调查,并帮忙您编写更快更有效的应用程序。 VisualStudio2020为VisualStudio分析器带来了更多改良功能,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 VisualStudio 分析器 找出 应用程序 瓶颈