将不确定变为确定~老赵写的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("\tTime Elapsed:\t\t" +
 68                watch.ElapsedMilliseconds.ToString("N0") + "ms");
 69             Console.WriteLine("\tTime Elapsed (one time):" +
 70                (watch.ElapsedMilliseconds / iteration).ToString("N0") + "ms");
 71             Console.WriteLine("\tCPU time:\t\t" + (ticks * 100).ToString("N0")
 72                + "ns");
 73             Console.WriteLine("\tCPU time (one time):\t" + (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("\tGen " + i + ": \t\t\t" + 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("\tTime Elapsed:\t\t" +
124                watch.ElapsedMilliseconds.ToString("N0") + "ms");
125             Console.WriteLine("\tTime Elapsed (one time):" +
126                (watch.ElapsedMilliseconds / iteration).ToString("N0") + "ms");
127             Console.WriteLine("\tCPU time:\t\t" + (ticks * 100).ToString("N0")
128                 + "ns");
129             Console.WriteLine("\tCPU time (one time):\t" + (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("\tGen " + i + ": \t\t\t" + 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吧!

本文转自博客园张占岭(仓储大叔)的博客,原文链接:将不确定变为确定~老赵写的CodeTimer是代码性能测试的利器,如需转载请自行联系原博主。

时间: 2024-09-29 19:27:20

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

老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高级语言更多的CLR细节.因此,如果您想要通过学习IL来了解CLR,那么这个过程很可能会"事倍功半".因此,从这个角度来说,老赵并不倾向于学习IL.不过严格说来,即使IL无法看出CLR的细节,也不足以说明"IL无用"--这里说"无用"自然有些夸张.但是

艾伟_转载:老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高级语言更多的CLR细节.因此,如果您想要通过学习IL来了解CLR,那么这个过程很可能会"事倍功半".因此,从这个角度来说,老赵并不倾向于学习IL.不过严格说来,即使IL无法看出CLR的细节,也不足以说明"IL无用"--这里说"无用"自然有些夸张.但是

艾伟:老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

在上一篇文章中,我们通过一些示例谈论了IL与CLR中的一些特性.IL与C#等高级语言的作用类似,主要用于表示程序的逻辑.由于它同样了解太多CLR中的高级特性,因此它在大部分情况下依旧无法展现出比那些高级语言更多的CLR细节.因此,如果您想要通过学习IL来了解CLR,那么这个过程很可能会"事倍功半".因此,从这个角度来说,老赵并不倾向于学习IL.不过严格说来,即使IL无法看出CLR的细节,也不足以说明"IL无用"--这里说"无用"自然有些夸张.但是

驳“反驳老赵之“伪”递归”

晚上看到鹤冲天的"反驳老赵之"伪"递归",大概看了一下,主要是反驳老赵提出的"伪"递归的概念,特别是"伪",看起来说的都很有道理,但我个人认为,老赵说的没有错,Lambda这种看上去是递归的方式,根本不算是递归. 我引用鹤冲天的递归概念: 一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法 我觉得这句话说的很明白,通俗点就是自己调用自己,鹤兄说递归应该不仅仅是过程还是函数,应该包括匿名方法和lambda.我同意匿名方

使用IE6看老赵的博客——比较完美版(可以在线查看、回复)

  上一个版本主要是测试一下我的想法,也是熟悉一下jQuery,代码这个东东不动手写一下是很难弄明白的.   有想法,写代码,出现错误,修改错误 = 不断进步.   带着问题去学习,动力就很大了.上一个版本能够看到了,但是还要修改URL,没看一篇都要改一下也太麻烦了.能不能点里面的连接,然后就直接看了呢?试了一下,很不幸又跳到那个郁闷的页面了.   怎么办呢?这就是问题.如何解决呢?修改连接,就是改一下a标签.点了之后不进行跳转不就行了吗?那我们还是来replace.   replace(/hr

把老赵的页面缓存片断改一下,呵呵

老赵同志写的页面缓存片断不错,用着方便,但我感觉在前端调用上有些不便,可以我把他的代码又改了一下,呵呵! 老赵代码的调用: Before Rendering: <%= DateTime.Now %> <br /> Rendering: <%= Html.Cache("Now", null, DateTime.Now.AddSeconds(60), Cache.NoSlidingExpiration, () => { System.Threading.

蟠桃如何策划营销老赵家海参店

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 最近蟠桃开始策划营销一个新的网站--老赵家海参店,最近开始对海参比较感兴趣,毕竟现在的人开始越来越重视健康和养生了,而且有钱的人对于养生的重视程度相对更高,而且海参,只要开始吃了,觉得不错,都会认准一个牌子,并且这种高端的保健食品的消费需求也是很大的,所以做海参就是要培养用户的口味.当然今天在这,蟠桃不是要讲海参的,而是讲解策划营销老赵家海参

使用IE6看老赵的博客 jQuery初探_jquery

很郁闷,看个博客吗,还要在安装一个浏览器?俺很懒,俺就是想要用IE6看! 最近在看jQuery,刚刚入一点门,发现了一个有趣的函数,就拿老赵的博客做实验了,哈. 装入一个 HTML 网页最新版本. jQuery 代码: 复制代码 代码如下: $.ajax({ url: "test.html", cache: false, success: function(html){ $("#results").append(html); } }); <div id=&qu

asp.net简单性能计数器---老赵版改良

   代码如下 复制代码 public static class CodeTimer     {         private static bool isQueryThreadCycleTime = false;         public static void Initialize()         {             Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;