现代软件工程讲义 2 开发技术 - 效能分析

[移山之道 第九章]

9.4  VSTS 效能分析工具

啊,效能分析,Performance!这是每一个程序员都梦想的事儿,让自己的程序跑得又快又好,最好是比别的同学快一个数量级,别人的程序是O(N^2),而我的程序是O(n*logN),或者是O(N)这是多爽的一项成就呀!VSTS提供了方便的效能分析工具,让我们能很快地找到程序的效能瓶颈,从而能有的放矢,改进程序。下面我们看一个具体的例子。

和同学们的作业类似,有这样一道题:

写一个程序,分析一个文本文件中各个词出现的频率,并且把频率最高的10个词打印出来。

 

果冻很快用C#写好了程序,命名为WordFreq.exe,然后运行了一下,验证了正确性,程序的基本框架如代码清单9-3所示(全部程序可以在移山社区网站下载):

代码清单9-3  WordFreq程序,程序框架

DoIt()

{

    ProcessFile()  //store all words in a big buffer

    ProcessBuffer()  //calculate and store the frequency of each word

    OutputResult()   //output top 10

}

 

ProcessBuffer()

{

    GetOneWord()   //get one word from buffer

    FreqOneWord()

}

 

FreqOneWord(word)

{

Find the word in the array list,

If (found)

    Update the frequency

If (not found)

    Add the word in the array list with frequency = 1

}

 

OutputResult()

{

ArrayList.Sort()   //sort the array

Output Top 10 entry;

}

文本文件大约是30KB~300KB大小。在运行效能分析之前,阿超让大家预计占用时间最多的是什么函数,或者哪些语句。大家众说纷纭,有的说是处理文件,因为I/O很花时间,有的说是排序,有的说是处理每个词。还有人建议应该把排序和处理每一个词同时进行,这样就能加快速度。

我们看看到底会是什么情况。第一步,要确保编译的程序是Release版本。然后在VS界面中选中Tools | Performance Tools | Performance Wizard(如图9-1所示)。

clip_image002

9-1  效能分析,选择分析方法

我们看到可以选择两种分析方法:

(1)        抽样(Sampling

(2)        代码注入Instrumentation

通俗地解释,抽样就是当程序运行时,Visual Studio时不时看一看这个程序运行在哪一个函数内,并记录下来,程序结束后,Visual Studio就会得出一个关于程序运行时间分布的大致的印象。这种方法的优点是不需要改动程序,运行较快,可以很快地找到瓶颈。但是不能得出精确的数据,代码中的调用关系(CallTree)也不能准确表示。

另一方面,代码注入就是将检测的代码加入到每一个函数中,这样程序的一举一动都被记录在案,程序的各个效能数据都可以被精准地测量。这一方法的缺点是程序的运行时间会大大加长,还会产生很大的数据文件,数据分析的时间也相应增加。同时,注入的代码也影响了程序真实的运行情况(这有点像量子物理学中的“测试的光线干扰了测试物体本身”的现象)。

我们一般的做法是,先用抽样的方法找到效能瓶颈所在,然后对特定的模块用代码注入的方法进行详细分析。

对程序进行效能分析,我们先要弄清下面这几个名词,如表9-1所示:

9-1  效能分析的名词解释

 

 

调用者Caller

函数Foo()中调用了Bar()Foo()就是调用者

被调用函数Callee

见上,Bar()就是被调用函数

调用关系树Call Tree

从程序的Main()函数开始,调用者和被调用函数就形成了一个树形关系—调用树

消逝时间Elapsed Time

从用户的角度来看程序运行所花的时间。当用户看到一个程序没有反应,用户并不知道程序此时是在运行自己的代码,还是被调度出去了,或者操作系统此时正在忙别的事情

应用程序时间Application Time

应用程序占用CPU的时间,不包括CPU在核心态时花费的时间

 

续表

 

 

本函数时间Exclusive Time

所有在本函数花费的时间,不包括被调用者使用的时间

所有时间Inclusive Time

包含本函数和所有调用者使用的时间

理解了上面的各种概念后,我们就不难理解“消逝的本函数时间(Elapsed Exclusive Time)”等其他组合名词所代表的概念了。

我们先进行抽样分析,在效能浏览器(Performance Explorer)中开始效能分析即可。

9-2WordFreq程序处理一个30KB的文本文件时的情况:

clip_image004

9-2  用抽样的方法分析效能

大家可以看到最花时间的三个函数是:

WordFreq.Freq.FreqOneWord(string)

System.String.EqualsHelper(string,string)

System.Collections.ArrayList.get_Item(int32)

三个函数加起来占用了整个程序84%的时间。看来我们得分析为什么这三个函数会被调用得这么频繁,开销这么大了。

们现在可以进行代码注入的分析,同样运行程序后,我们看看图9-3的调用树(Call Tree报告。

clip_image006

9-3  代码注入方法产生的效能报告

 

结合实际的代码(见代码清单9-4),可以看到在WordFreq. FreqOneWord函数中,究竟发生了什么:

代码清单9-4  FreqOneWord()

        private void FreqOneWord(string w)

        {

            // see if we have a match, if not, add it to the end,

            // then assign it initial frequency 1;

            // if yes, inc the frequency by 1

            for (int i = 0; i < m_wordList.Count; i++)

            {

                Frequency fi = (Frequency)m_wordList[i];

 

                if (fi.str == w)

                {

                    fi.n++;

                    return;

                }

            }

 

            //now we have to append it to the end.

            Frequency f = new Frequency();

            f.str = w;

            f.n = 1;

            m_wordList.Add(f);

        }

我们可以清楚地看到:

WordFreq.Freq.FreqOneWord(string)被调用了8 150次,说明有8 150个词被处理了。但是,System.Collections.ArrayList.Add(object)被调用了1 112次,说明有1 112个不同的词被加入到ArrayList中。下面三个函数被调用的次数相似,它们都花了很多的时间。

System.Collections.ArrayList.get_Count()

System.Collections.ArrayList.get_Item(int32)

System.String.op_Equality(string,string)

 

果冻:(大叫起来)当我写这一个语句的时候

      for (int i = 0; i < m_wordList.Count; i++)

没想到m_wordList.Count,也就是ArrayList.GetCount(),会花这么多时间,累计被调用了1631884次!

我可以马上把代码改成:

            int count = m_wordList.Count;

for (int i = 0; i < count; i++)

这样会如何?大家等了一会儿,代码分析的结果出来了(如图9-4所示):

clip_image008

9-4  改进过的程序效能分析图

可以看到System.Collections.ArrayList.get_Count()的调用次数和时间都大幅度地下降了。

我们可以继续进行“效能测试,分析,改进,再效能测试”的流程,逐渐提高程序的效能和我们的编程水平。

大家也要注意避免没有做分析就过早地进行“效能提高”,刚才有人提到我们可能要提高排序的性能,但是从图9-4来看,System.Collections. ArrayList.Sort()只占了FreqOneWord()不到1/50的时间,如果我们不经分析就盲目优化,也许会事倍功半。

9.5  本章讨论

果冻噫吁唏,危乎高哉!我以前一直害怕做效能分析,看来是否会用效能分析工具来提高程序质量是一个优秀程序员的标志之一。我在今天之前都是盲人骑瞎马。

小飞:改成盲人摸象更恰当。我听说,如果一个程序员从来没有用过效能分析工具,那他就不是一个程序员,只是一个编程爱好者罢了。

我的WC 程序事实上是最快的。但是在今天的程序评比之前,我想更进一步,就再优化了一下,估计能把速度提高2%。没想到出了一个小错误,导致报告的结果(行数、词数、字数)仅仅差了1。由于程序不正确,因此不能参加速度评比。我才是最需要大喊“噫吁唏”的人。

阿超:这有两个教训:

1)先保证正确性,再提高效能。一个“仅仅差了1”的错误可能会导致缓冲区溢出(Buffer Overflow)的严重漏洞。

2)如果效能的提高效果在5%以下,用户不会注意到程序效能的区别。所以要考虑那些微小的提高是否值得。

另外,WordFreq算法的时间复杂度是多少,能否再优化?请写实际程序加以验证。

荔荔:怎么才能快捷地得到有适量重复文字的文件,来帮助我们进行测试和效能分析?

九条:我是这样做的,在电脑的根目录下,运行“dir /s > c:\temp\test.txt”命令。

阿超:好主意,大家还有没有别的办法?

 

VS2012:

Visual Studio 2012 提供了更好的效能测试的功能, 请看这些博客:

  http://www.cnblogs.com/smart-code/archive/2012/09/23/2699053.html 

  http://www.cnblogs.com/Gun-N-Rose/archive/2012/09/23/2699220.html 

  http://www.cnblogs.com/bigbadwolf/archive/2012/09/24/2699438.html  

  http://www.cnblogs.com/Gun-N-Rose/archive/2012/09/24/2699804.html 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/500431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现代软件工程讲义 2 开发技术 - 单元测试 amp; 回归测试

[移山之道 第11章] 1单元测试 你的RP是由你的程序质量决定的。 ——阿超 这一章讲的是两人合作&#xff0c;既然程序是两个人写的&#xff0c;那就会出现一个人写的模块被另一个人写的模块调用的情况。很多误解、疏忽都发生在两个模块之间。如何能让自己写的模块尽量无懈可击…

现代软件工程讲义 4 方法论 - MSF

[内容来自 移山之道]白话MSF方法论 2.1 果冻的预习果冻&#xff1a;超总&#xff0c;听说你要讲MSF&#xff0c;我就先预习了一下&#xff0c;但是MSF的名词太多了&#xff0c;我真是头大&#xff0c;能不能解释一下这两句&#xff1a; “MSF的一个基础原理是学习所有的经验。…

现代软件工程讲义 9 测试 关于闰年的测试

我们谈了不少测试的名词, 规范和原则 (link1, link2). 软件是人写的, 测试计划和测试用例也是人写的, 人总会犯错误。错误发生之后, 总有人问: 为什么这个bug 没有测出来啊?! 我们看看一类简单的bug是如何发生的&#xff0c;以及如何预防它们再度发生: 闰年 软件少不了和…

现代软件工程 来自卓越大学教师的建议 (读书笔记)

教师教学有培训和参考书么? 我从来没想到过我会在大学里教书, 而且还教了好几年, 四个学校。 当时接到任务的时候, 我把它当作实习生培训和新员工培训的”学院版”, 还是继续强调实践, 反馈, 合作, 就这么开讲了。 在微软公司, 做大部分和人相关的事情, 都得先有一个培训, …

软件工程讲义 9 创新的出路 走进作坊

我第一次注意到 “作坊”这个词和软件行业联系起来大概是这个 2004 年 11 月的报道: 标题: 信产部副部长娄勤俭&#xff1a;中国软件业还在手工作坊阶段 日前&#xff0c;信息产业部副部长娄勤俭在出席中国软件产业生态链高层论坛时表示&#xff0c;中国软件产业的规模还比较小…

现代软件工程 习而学的软件工程教育

茅于轼先生写了一篇博客 ( http://blog.sina.com.cn/s/blog_49a3971d0102dufj.html ) 纪念茅以升先生提出的 习而学的工程教育: 把颠倒了的工程教育顺序恢复过来&#xff0c;即他称之谓“习而学的工程教育”。 以桥梁建筑专业为例&#xff0c;大学一年级先学施工条例&#xff0…

现代软件工程 教课心得

现实世界是最好的老师, 我们这些叫 “老师” 的人, 充其量是个助教。 但是有些助教却不让学生见到老师。 **************** 老师都想把课教好, 学生都想把课学好. 但是我们常常看到一个学期过后, 老师, 学生都有很多抱怨 (例如: 各种良好愿望和计划在实施中的问题). 看了上…

微软学术搜索项目 10个版本的历程

这是我在微软亚洲研究院参与的项目之一, 从 2009 年秋天开始, 我们小组把它从一个研究原型发展为涵盖全学科的学术搜索门户。 它索引了 4千万论文, 2千万作者, 6 大实体类型, 8 种数据可视化功能, 具有开放的API 平台和手机客户端. 下面说说项目的发展: 2009/8: 内部发布 alp…

现代软件工程讲义 9 测试 QA 的角色和分工

测试的角色 (Test) 要独立出来么 ? 独立出来的测试角色怎么才能发挥作用? 有些成功人士和成功的公司号称没必要有独立的测试角色 (Test), 你怎么看? 最近又看到一些关于开发人员要不要负责测试的讨论。 例如: http://www.aqee.net/on-testers-and-testing/ 大多数的开发…

程序设计作业: 车模+数模 = ?

我上学的时候只听说过 “航模”, 没听说过“数学建模”这门学问. 这几年在简历里看到过不少人号称数模得过什么奖之类的, 我都没好意思问太仔细。 在帝都开车经常遇到堵车, 我于是想到了一个车模的问题。 我想请大家帮着给这个车模搞个数模, 求个解法: 想象帝都北四环或北五…

计算机考研的调查和改进建议

几星期前, 我在微博上讨论考研的事, 有专家建议不如把意见整理出来, 说不定可以转告给相关方面。 我没有考过研, 问了公司的同事们, 绝大多数都是保研的, 也没考过。 我从网上下了一份模拟题, 好像还挺难&#xff0c;有一种要翻书的冲动。 全国有多少学生为了考研而奋斗? …

2012 夏季高校微软俱乐部活动 - 开门创新

创新啊创新, 大家都在讲创新。 一般的理解, 创新就是公司内部关起门来想, 实验, 内部评审, 然后申请专利什么的, 其实也有开门创新的办法: http://www.innovationexcellence.com/blog/2012/08/13/40-examples-of-open-innovation-crowdsourcing/ it is about bringing extern…

笔记 - 高等教育的创新

教育是一个社会发展的支柱, 你和我能看到并理解这个博客, 教育功不可没。 高等教育的形式并不是一成不变的, 高等教育一直在演进, 变革中, 最近一股“online higher education” 的浪潮在美国兴起, 貌似突兀, 其实有规律可循。 在关注最近的在线教育浪潮之前, 我们看看美国高等…

现代软件工程讲义4 Scrum/Sprint

Advanced Software Engineering, Development Process, Scrum/Sprint 软件开发的流程有很多 (看 各种方法论概述), 我也写过一篇博客 (酒后的敏捷) 谈了谈最近比较时髦的开发流程。 今天我们不喝酒, 正襟危坐地说说敏捷这一路 Scrum/Sprint 开发方法. 从理论上看, 这个方法真…

现代软件工程讲义 7 设计阶段 Spec

在前一个博客里 (典型用户), 我们讲了怎么收集, 分析和验证用户的需求。 这里我们讲 spec – specification Specification, 又叫spec, 有两种: a) functional spec, 软件功能说明书, 主要用来说明软件的外部功能, 和用户的交互情况 (把软件当作一个黑盒子) b) technical spec…

现代软件工程 2012 北航 项目复审模板

这是现代软件工程课在北航的项目复审要求。 这次我们有下列 10 个团队, 他们做了一些有意思的项目&#xff1a; 有七个小组合作&#xff0c;携手打造一个叫 学霸 的网站: 100Years 网页收集和归类工具76er 网页收集和归类工具FightingSnail 网页元数据抽…

现代软件工程讲义 8 软件的血型

[这是 现代软件工程讲义 的一篇] 一个软件团队经历了计划/设计/开发等阶段, 达成代码完成 (Code Complete) 这一目标&#xff0c;似乎后面的事情就水到渠成了. 其实不然, 软件生命周期的最后阶段往往是最考验团队的&#xff0c;不但考验团队项目管理水平&#xff0c;应变能力…

现代软件工程讲义 6 用户调研

[现代软件工程讲义 的一部分] 软件开发的过程, 就是 “用户最需要的东西” 在下面这一链条中传送&#xff0c;转换&#xff0c;实现&#xff0c;扭曲或丢失的过程。 用户最需要的 > 用户表达出来的 > 软件团队能理解的 (老板/PM) 团队的商业目标 > 软件团队成员具…

软件工程讲义 0 微博上的软件工程

[现代软件工程讲义] 有舌尖上的美味, 也有微博上的软工。舌尖上的美味各有千秋, 而微博上对软工的抱怨都是相似的。 下面是我在新浪微博收集到大学生对软件工程教学的反馈: 师生关系&#xff08;不限于软件工程&#xff09; 教材 上课 & 老师 实践 & 作业 考试 考完…

现代程序设计 作业 2

我们上节课讲了 返回整数数组中最大子数组的和 这个问题。 我们第二次作业在这个基础上扩展。 程序要使用的数组放在一个叫 input.txt 的文件中, 文件格式是: 数组的行数, 数组的列数, 每一行的元素, (用逗号分开) 每一个数字都是有符号32位整数, 见 MSDN 的定义. 当然, 行…