zoukankan      html  css  js  c++  java
  • 第三周-词频统计效能分析

    效能分析作业具体要求如下:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/956

    这篇博客由如下几个方面进行阐述:

    1.预备工作

    2.性能分析

    3.优化修改

    4.学习总结

    一.预备工作

    git地址:https://coding.net/u/huyr000/p/countWords/git

    1.要求:重定向由文件系统读入,连续三次运行结果

    三次运行结果截图:

    三次平均运行时间大概在5.7s左右,CPU占用20%~40%。

    2.我猜测程序的瓶颈代码段如下

     rline = rline.ToLower();

    之所以认为此处是瓶颈,是因为曾经看过一篇文章,说一般语言自带的函数会比自己定义的函数慢一点,如果自己定义一个优化的大写转小写函数应该快一点。

    预计优化后会运行时间会少一秒左右。

    二.性能分析

          我使用的是vs自带性能分析工具Profiler,主要用来提升性能和寻找瓶颈。在主菜单中的调试选项中,就会有对应的性能分析的选项。如果你发现没有这个选项,那么,你需要安装一个更为强大的VisualStudio版本,Team系列的VS才会有这个工具的安装。

          Profiler很强大,你可以用它分析一个二进制文件,可以用它分析一个工程,也可以用它分析一个网站。无论是C#、VC还是VB,它能很好的分析。你可以用Profiler对一个Target做很多事情。最重要的当属函数执行时间的分析,Profiler会给出函数的执行时间,执行次数,执行时间占整个程序的百分比;更强大的是,他可以给出一个调用树,这样,你可以在Profiler中查看这个程序到底是如何被一步步调用的。查看的过程中,你还能看到这些函数的执行百分比,你可以非常方便的找到最耗时的函数。一层层的查下去,原来瓶颈就是那个你可能都没有正眼看过的小函数。感谢Profiler,你可以有目的的优化你的程序了。优化以后,你总得看看效果吧,于是再利用Profiler进行分析,然后呢?Profiler提供结果比较功能,很好很强大。你可以通过这个功能看看你的程序,哪些函数的执行效率提升了,哪些又降低了。很方便。

    我使用vs2010自带的性能分析工具时:

    自带的性能分析工具包含如下四个方面的内容:

    进行下一步的时候出现了这个问题:

    解决方案:要在/standalone Profiler路径下安装vs_profiler.exe,因为我在安装的时候没有standalone Profiler目录,并且vs2010没有提供实现重定向的一个属性IsInputRedirected,所以就重装vs2015版本。vs下载链接[http://down.nenu.edu.cn/]

    vs2015版本相对于vs2010版本,多了几个功能。CPU使用率,GPU使用情况,内存使用率

    当点击性能向导时,便出现了vs2010版本的4项分析

    第一次分析结果

    CPU使用百分率

    CPU运行时间和进程内存的分析

    GPU使用情况

    调用函数分析

    函数占用比的分析

    代码的分析

    三.优化修改

    1.修改一

    某个方法实现所包含的代码路径可能导致对同一对象多次调用Dispose 等效的方法(例如,用于某些类型的 Close() 方法)。正确实现的 Dispose方法可以调用多次,而不会引发异常。 然而,这是无法保证的。为避免生成 System.ObjectDisposedException,不应对一个对象调用 Dispose 多次。

    需优化代码块:

     private static string ReadFile(string file)
            {
                string rline;
                FileStream fs = new FileStream(file, FileMode.Open);
                StreamReader sr = new StreamReader(fs);
                rline = sr.ReadToEnd();
                sr.Close();
                fs.Close();
                return rline;
            }

    解决方法:使用 try/finally 块,在 finally 块中,确保 stream 资源不为 null。

    更改后代码如下:

     private static string ReadFile(string file)
            {
                try
                {
                    string rline = null;
                    FileStream fs = new FileStream(file, FileMode.Open);
                    StreamReader sr = new StreamReader(fs);
                    rline = sr.ReadToEnd();
                    return rline;
                }
                finally
                {
                    if (sr != null && fs != null)
                    {
                        sr.Dispose();
                        fs.Dispose();
                    }
                }
    }

    最终改为:

    //获取控制台重定向文件数据流
                        StreamReader ioIn = null;
                        ioIn = new StreamReader(Console.OpenStandardInput());
                        string rline;
                        rline = ioIn.ReadToEnd();

    2.修改二

    根据profile分析的结果,System.Object.Equals(object)函数消耗时间较多。

    需优化代码:

     if (args.Length >0 &&args.Equals("-s"))

    C#中常见的比较字符串的方法有Compare、CompareTo、Equals、==方法。后来随便写了个程序用三种方法比较两个简单的字符串,得出的结论是直接用“==”最快

    更改后的代码如下:

     if (args.Length >0 && args[0] == "-s")

    3.修改三

    需优化代码:

    rline = rline.ToLower();

    写了一个自己定义的大写转小写的函数

    public static StringBuilder ToLower(StringBuilder str) 
            {
                for (int i = 0; i < str.Length; i++) 
                {
                    if (str[i] <= 'Z') 
                    {
                        str[i] =(char) ((int)str[i]+32);
                    }
                }
                    return str;
            }

    调用变为:

    rline = ToLower(rline);

    最终优化后运行截图:

    运行时间由5s多变为0.5s多了呢,开心

    用老师推荐的ptime.exe测试时间截图如下:

    通过优化之后,发现运行时间变少,与其他同学的程序结果对同一war_and_peace.txt比较,发现单词的总量和每个单词出现的总数类似(相差度不超过十),精确度变高了。优化之前的单词总量和词频都是有错的。

    再次profile得到的结果如下:

    CPU使用百分率:

    函数占用比:

    为什么会这样呢?

    为什么只能分析一个工作函数?

    然后我使用另外一种方法再次测试,用.exe文件进行测试,具体操作如下:

    然后进行分析,得到了报错,不支持IO重定向测试。

    这时候我又在想为什么我能得到优化前的equals()函数占用比,那时候也是不支持IO重定向的呀。然后又对以前的代码进行测试,发现能得到以前的equals()函数的占用比,是因为先前的代码并没有持续进行,只能探测到equals()就被暂停了。

    因为无法进行重定向,想办法解决,解决方案:在调试选项中选择wf属性,然后再进行profile。

    具体操作如下:调试 -> wf属性 ->命令行参数设定如下

    函数执行占比如下:

    优化前最花费时间的3个函数为正则,分割字符串,哈希表。

    因为优化后运行时间少于1s,所以我挂起了2s。此时运行截图为:

    注意点:当优化后的运行时间如果少于1s(秒级),就得不到分析结果,如果你优化后程序运行时间少于1s左右,此时你就可以用sleep()函数,可以让它挂起1000ms以上,再测试就会有分析结果出现了。

    再一次profile:

    优化后最花费时间的函数:正则,分割字符串,哈希表,IO流。

    四.学习总结

           通过这次对程序进行效能分析,知道了效能分析的大致流程。实践第一步是要确保编译的程序是Release版本,然后在visual studio界面中选中Tools | Performance Tools | Performance Wizard,先用抽样的方法找到效能瓶颈所在,然后对特定的模块用代码注入的方法进行详细分析。在效能分析过程中要一直反复进行“效能测试,分析,改进,再效能测试”的流程,才能逐渐提高程序的效能和我们的编程水平。也要避免没有做分析就过早进行优化,“过早优化是万恶之源”。如果我们不经分析就盲目优化,也许只能达到事倍功半的效果。

  • 相关阅读:
    webpack安装填坑('webpack' 不是内部或外部命令,也不是可运行的程序或批处理文件)
    JS中let和var的区别(附加const声明特点)
    浅谈 var bool= false 和 var bool= new Boolean(false)的区别
    "if (!(""a"" in window)) { var a = 1; } alert(a); 为什么结果是undefined"
    浅谈display: none、visibility: hidden、overflow: hidden、opacity: 0
    10Git服务器搭建
    09Git GitHub
    08Git标签
    07Git查看提交历史
    自举驱动电路原理
  • 原文地址:https://www.cnblogs.com/huyourongmonkey/p/7581219.html
Copyright © 2011-2022 走看看