zoukankan      html  css  js  c++  java
  • 执行性能测试—起步

    程序越来越大,为了让程序更快地响应用户的输入,需要执行性能测试,最近在研究性能测试,就从这篇最基础的文章开始起步吧。VS 2010自带了一个功能强大的性能测试工具—Performance Wizard,在研究过程中,我决定用通过分析最普通的排序操作的程序来开始我的学习过程。

    程序的功能很简单,接受任何文本文件,排序,然后将结果输出到一个新的文件中。第一个版本很简单,使用最好写的冒泡排序实现:

            #region 常见的排序方法 适合小文件的排序

            static void Main(string[] args)

            {

                if (args.Length != 2)

                {

                    Console.WriteLine("Usage: sort <file name> <output file name>");

                    return;

                }

     

                string[] sortedLines;

                using (StreamReader reader = new StreamReader(Path.GetFullPath(args[0])))

                {

                    var text = reader.ReadToEnd();

                    sortedLines = Sort(text);

                }

     

                using (StreamWriter writer = new StreamWriter(Path.GetFullPath(args[1])))

                {

                    foreach (var line in sortedLines)

                        writer.WriteLine(line);

                }

            }

     

            #region 使用冒泡排序来测试性能

            // V1: 使用冒泡排序来测试性能

            private static string[] Sort(string text)

            {

                var lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);

     

                for (int i = 0; i < lines.Length; ++i)

                {

                    for (int j = i + 1; j < lines.Length; ++j)

                    {

                        if (string.CompareOrdinal(lines[i], lines[j]) < 0)

                        {

                            var temp = lines[i];

                            lines[i] = lines[j];

                            lines[j] = temp;

                        }

                    }

                }

     

                return lines;

            }

            #endregion

    使用一个大小为2.5 兆的文本文件作为输入数据,并且用下面的步骤执行性能测试:

    1.         打开Visual Studio,并点击菜单栏里的“分析(Analyze)”。

    2.         点击“启动性能测试向导(Launch Performance Wizard)”。

    3.         在“性能测试向导(Performance Wizard)”页面上选择“CPU Sampling (recommended)”。

    4.         在后续页面上,使用页面默认的选项做完设置。

    耐心等待程序执行完以后,Visual studio会提供一个报表,在摘要(Summary)里面—下图,可以看到,程序使用了大约36秒才完成了所有的过程。

    另外,在Hot Path表格里,也可以看出,String.CompareOrdinal函数所占用的时间是最多的,占整个程序执行的78.44%。而从另外一个统计表Functions,这个统计表显示了在程序执行完毕之前,函数触发样例的次数,注意,这个样例触发的次数和函数被调用的次数没有对应关系,两个样例之间,函数可能被调用了多次,而且多个函数也可能被调用到—这个跟我们使用“CPU Sampling (recommended)”的策略有关,它的优点是快不影响被测程序的运行,缺点就是不够精确。从Functions的统计表里面,可以看到String.CompareOrdinal被调用到的次数是其他函数的好几倍:

     

    既然已经知道冒泡排序是整个程序的瓶颈了,那我们第二个版本就是将冒泡算法改成快速排序,看看有没有改进:

    #region 常见的排序方法 适合小文件的排序

            static void Main(string[] args)

            {

                if (args.Length != 2)

                {

                    Console.WriteLine("Usage: sort <file name> <output file name>");

                    return;

                }

     

                string[] sortedLines;

                using (StreamReader reader = new StreamReader(Path.GetFullPath(args[0])))

                {

                    var text = reader.ReadToEnd();

                    sortedLines = Sort(text);

                }

     

                using (StreamWriter writer = new StreamWriter(Path.GetFullPath(args[1])))

                {

                    foreach (var line in sortedLines)

                        writer.WriteLine(line);

                }

            }

     

            #region 使用快速排序来测试性能

            // V2: 使用快速排序来测试性能

            private static string[] Sort(string text)

            {

                var lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);

     

                QuickSort(lines, 0, lines.Length - 1);

     

                return lines;

            }

     

            private static int Partition(string[] lines, int lower, int upper)

            {

                var pivot = lines[upper];

                var newPivot = lower - 1;

     

                for (int i = lower; i < upper; ++i)

                {

                    if (string.CompareOrdinal(pivot, lines[i]) > 0)

                    {

                        var temp = lines[i];

                        newPivot = newPivot + 1;

                        lines[i] = lines[newPivot];

                        lines[newPivot] = temp;

                    }

                }

     

                ++newPivot;

                lines[upper] = lines[newPivot];

                lines[newPivot] = pivot;

                return newPivot;

            }

     

            private static void QuickSort(string[] lines, int lower, int upper)

            {

                if (lower < upper)

                {

                    var pivot = Partition(lines, lower, upper);

                    QuickSort(lines, lower, pivot - 1);

                    QuickSort(lines, pivot + 1, upper);

                }

            }

            #endregion

     

            #endregion

    这次的结果要比上次好很多,这次只用了3秒多就完成了所有的工作,而且在Hot Path里面,String.CompareOrdinal函数在程序执行时间的比重也下降了很多。

    虽然我们从总的执行时间上来看,看到了很大的性能提高,但是知道那些函数的执行效率提高了,会让你更直观的感觉到后续性能优化的目标。VS 2010支持对比多个性能报告,并给出两个报告之间的差别,例如哪些函数的执行速度有提高之类的:

    1.         点击菜单栏里的“分析(Analyze)”。

    2.         点击“Compare Performance Report”,在弹出来的对话框里选择两个性能测试的报告。

    上图里,我在“Column 里面选择了“Exclusive Samples”—因为对比百分比对我来说不够直观。从对比的结果来看,快速排序在各个方面全面胜出—除了Partition函数,因为那是一个新函数。

    接下来,为了查看快排对大文件排序的性能,我使用了一个700多兆的文本文件进行测试,这次—程序崩溃了,崩溃的原因是OutOfMemoryException……

    下一篇讲解OutOfMemoryException的分析过程。

  • 相关阅读:
    分布式系统与机器学习相关笔记
    天坑:OpenGL制作游戏引擎备忘记录
    2016ACM-ICPC 大连站、青岛站、China-Final 赛后总结(无删版)by wanglangzhe || wmzksana
    CF 609E, 树链剖分
    CF 609F,线段树上二分 + set维护
    CF 540E, 树状数组
    hdu 5726, 2016多校1
    hdu5836, 2016CCPC网络赛
    SYSU-10,URAL 1675,容斥原理
    动态规划基础篇 from 51nod
  • 原文地址:https://www.cnblogs.com/killmyday/p/1761583.html
Copyright © 2011-2022 走看看