• 将不确定变为确定~老赵写的CodeTimer是代码性能测试的利器


    首先,非常感谢赵老大的CodeTimer,它让我们更好的了解到代码执行的性能,从而可以让我们从性能的角度来考虑问题,有些东西可能我们认为是这样的,但经理测试并非如何,这正应了我之前的那名话:“机器最能证明一切”!

    费话就不说了,看代码吧:

    复制代码
      1     /// <summary>
      2     /// 执行代码规范
      3     /// </summary>
      4     public interface IAction
      5     {
      6         void Action();
      7     }
      8 
      9     /// <summary>
     10     /// 老赵的性能测试工具
     11     /// </summary>
     12     public static class CodeTimer
     13     {
     14         [DllImport("kernel32.dll", SetLastError = true)]
     15         static extern bool GetThreadTimes(IntPtr hThread, out long lpCreationTime, out long lpExitTime, out long lpKernelTime, out long lpUserTime);
     16 
     17         [DllImport("kernel32.dll")]
     18         static extern IntPtr GetCurrentThread();
     19         public delegate void ActionDelegate();
     20         private static long GetCurrentThreadTimes()
     21         {
     22             long l;
     23             long kernelTime, userTimer;
     24             GetThreadTimes(GetCurrentThread(), out l, out l, out kernelTime, out userTimer);
     25             return kernelTime + userTimer;
     26         }
     27         static CodeTimer()
     28         {
     29             Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
     30             Thread.CurrentThread.Priority = ThreadPriority.Highest;
     31         }
     32         public static void Time(string name, int iteration, ActionDelegate action)
     33         {
     34             if (String.IsNullOrEmpty(name))
     35             {
     36                 return;
     37             }
     38             if (action == null)
     39             {
     40                 return;
     41             }
     42 
     43             //1. Print name
     44             ConsoleColor currentForeColor = Console.ForegroundColor;
     45             Console.ForegroundColor = ConsoleColor.Yellow;
     46             Console.WriteLine(name);
     47 
     48             // 2. Record the latest GC counts
     49             //GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
     50             GC.Collect(GC.MaxGeneration);
     51             int[] gcCounts = new int[GC.MaxGeneration + 1];
     52             for (int i = 0; i <= GC.MaxGeneration; i++)
     53             {
     54                 gcCounts[i] = GC.CollectionCount(i);
     55             }
     56 
     57             // 3. Run action
     58             Stopwatch watch = new Stopwatch();
     59             watch.Start();
     60             long ticksFst = GetCurrentThreadTimes(); //100 nanosecond one tick
     61             for (int i = 0; i < iteration; i++) action();
     62             long ticks = GetCurrentThreadTimes() - ticksFst;
     63             watch.Stop();
     64 
     65             // 4. Print CPU
     66             Console.ForegroundColor = currentForeColor;
     67             Console.WriteLine("	Time Elapsed:		" +
     68                watch.ElapsedMilliseconds.ToString("N0") + "ms");
     69             Console.WriteLine("	Time Elapsed (one time):" +
     70                (watch.ElapsedMilliseconds / iteration).ToString("N0") + "ms");
     71             Console.WriteLine("	CPU time:		" + (ticks * 100).ToString("N0")
     72                + "ns");
     73             Console.WriteLine("	CPU time (one time):	" + (ticks * 100 /
     74                iteration).ToString("N0") + "ns");
     75 
     76             // 5. Print GC
     77             for (int i = 0; i <= GC.MaxGeneration; i++)
     78             {
     79                 int count = GC.CollectionCount(i) - gcCounts[i];
     80                 Console.WriteLine("	Gen " + i + ": 			" + count);
     81             }
     82             Console.WriteLine();
     83         }
     84 
     85 
     86 
     87         public static void Time(string name, int iteration, IAction action)
     88         {
     89             if (String.IsNullOrEmpty(name))
     90             {
     91                 return;
     92             }
     93 
     94             if (action == null)
     95             {
     96                 return;
     97             }
     98 
     99             //1. Print name
    100             ConsoleColor currentForeColor = Console.ForegroundColor;
    101             Console.ForegroundColor = ConsoleColor.Yellow;
    102             Console.WriteLine(name);
    103 
    104             // 2. Record the latest GC counts
    105             //GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    106             GC.Collect(GC.MaxGeneration);
    107             int[] gcCounts = new int[GC.MaxGeneration + 1];
    108             for (int i = 0; i <= GC.MaxGeneration; i++)
    109             {
    110                 gcCounts[i] = GC.CollectionCount(i);
    111             }
    112 
    113             // 3. Run action
    114             Stopwatch watch = new Stopwatch();
    115             watch.Start();
    116             long ticksFst = GetCurrentThreadTimes(); //100 nanosecond one tick
    117             for (int i = 0; i < iteration; i++) action.Action();
    118             long ticks = GetCurrentThreadTimes() - ticksFst;
    119             watch.Stop();
    120 
    121             // 4. Print CPU
    122             Console.ForegroundColor = currentForeColor;
    123             Console.WriteLine("	Time Elapsed:		" +
    124                watch.ElapsedMilliseconds.ToString("N0") + "ms");
    125             Console.WriteLine("	Time Elapsed (one time):" +
    126                (watch.ElapsedMilliseconds / iteration).ToString("N0") + "ms");
    127             Console.WriteLine("	CPU time:		" + (ticks * 100).ToString("N0")
    128                 + "ns");
    129             Console.WriteLine("	CPU time (one time):	" + (ticks * 100 /
    130                 iteration).ToString("N0") + "ns");
    131 
    132             // 5. Print GC
    133             for (int i = 0; i <= GC.MaxGeneration; i++)
    134             {
    135                 int count = GC.CollectionCount(i) - gcCounts[i];
    136                 Console.WriteLine("	Gen " + i + ": 			" + count);
    137             }
    138             Console.WriteLine();
    139         }
    140     }
    复制代码

    有了上面的codeTimer我们就来测试一个吧,如字条串和并的问题,用+=还是用StringBuilder呢,有点经验的程序员肯定说是StringBuilder,是的,确实是后者,那我们就来看看这

    两种方法测试的结果吧

    复制代码
     1      CodeTimer.Time("String  Concat", 100000,
     2                  () =>
     3                  {
     4                      var s = "1";
     5                      for (int i = 1; i < 10; i++)
     6                          s = s + "1";
     7                  });
     8 
     9       CodeTimer.Time("StringBuilder Concat", 100000,
    10                () =>
    11                {
    12                    var s = new StringBuilder();
    13                    for (int i = 1; i < 10; i++)
    14                        s.Append("1");
    15                });
    复制代码

    测试的结果如下:

    从图中我们可以看到StringBuilder快的很明显,无论是执行时间,还是对CPU的消耗及GC回收都远低于String的拼结,所以,才有以下结论:

    在字符串拼结时,请使用StringBuilder吧!

  • 相关阅读:
    requests
    urllib
    爬虫初入
    Django之admin
    Django之FileField字段
    边学边练之博客园----登录验证
    边学边练之博客园----设计表
    Django之中间件
    计算机基础
    win—命令行窗口一层一层的打开文件
  • 原文地址:https://www.cnblogs.com/jjg0519/p/8309590.html
Copyright © 2020-2023  润新知