我们在开发的过程中,很多时候一个功能可能有多个实现方法,为了追求代码的性能,我们往往需要比较各实现方法的运行时间,从而选择性能最好的实现方法。那么怎样计算一段代码(或者说是函数)的运行时间呢,这个就是这篇文章我们要总结的内容。我们主要分以下几点来总结。

  1. 在C#代码中计算代码执行时间
  2. 在Sql Server中计算代码执行时间

在C#代码中计算代码执行时间

在C#程序中要计算代码段(或方法)的执行时间,我们一般都使用Stopwatch类,我比较了使用+=和使用StringBuilder分别拼接字符串的性能差异,示例代码如下。

 1 namespace ConsoleApplication5
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             // 初始化性能计数器
 8             CodeTimer.Initialize();
 9 
10             // 定义执行次数
11             int iteration = 100 * 1000; //10万次
12 
13             string s = string.Empty;
14             CodeTimer.Time("String Concat", iteration, () => 
15             {
16                 s += "a"; 
17             });
18 
19             StringBuilder sb = new StringBuilder();
20             CodeTimer.Time("StringBuilder", iteration, () => 
21             {
22                 sb.Append("a"); 
23             });
24 
25             Console.ReadKey();
26         }
27     }
28 }

运行结果如下图。

我这里使用了封装的一个性能计时器,文章后面会附上源代码。

在Sql Server中计算代码执行时间

sql server中一般使用GetDate和DateDiff函数来计算sql语句运行的时间,示例代码如下。

 1 USE PackageFHDB;
 2 GO
 3 
 4 -- 开始时间
 5 DECLARE @t1 AS DATETIME;
 6 SELECT @t1= GETDATE();
 7 
 8 -- 运行的sql语句
 9 SELECT TOP 1000 * FROM dbo.Pkg_PkgOrderMaster;
10 
11 -- 打印结果
12 PRINT DATEDIFF(millisecond,@t1,GETDATE());

执行结果为293毫秒,如下图。

附:性能计时器的源代码

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Diagnostics;
 6 using System.Threading;
 7 using LNFramework.Common.Extends;
 8 using System.Runtime.InteropServices;
 9 
10 namespace LNFramework.Common.Tools
11 {
12     /// <summary>
13     /// 性能计时器
14     /// </summary>
15     public static class CodeTimer
16     {
17         /// <summary>
18         /// 初始化
19         /// </summary>
20         public static void Initialize()
21         {
22             // 将当前进程及线程的优先级设为最高,减少操作系统在调度上造成的干扰
23             // 然后调用一次Time方法进行预热,以便让Time方法尽快进入状态
24             Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
25             Thread.CurrentThread.Priority = ThreadPriority.Highest;
26             Time("", 1, () => { });
27         }
28 
29         /// <summary>
30         /// 计时
31         /// </summary>
32         /// <param name="name">名称</param>
33         /// <param name="iteration">循环次数</param>
34         /// <param name="action">方法体</param>
35         public static void Time(string name, int iteration, Action action)
36         {
37             if (name.IsNullOrEmpty()) return;
38 
39             // 1.保留当前控制台前景色,并使用黄色输出名称参数
40             ConsoleColor currentForeColor = Console.ForegroundColor;
41             Console.ForegroundColor = ConsoleColor.Yellow;
42             Console.WriteLine(name);
43 
44             // 2.强制GC进行收集,并记录目前各代已经收集的次数
45             GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
46             int[] gcCounts = new int[GC.MaxGeneration + 1];
47             for (int i = 0; i <= GC.MaxGeneration; i++)
48             {
49                 gcCounts[i] = GC.CollectionCount(i);
50             }
51 
52             // 3.执行代码,记录下消耗的时间及CPU时钟周期
53             Stopwatch watch = new Stopwatch();
54             watch.Start();
55             ulong cycleCount = GetCycleCount();
56             for (int i = 0; i < iteration; i++)
57             {
58                 action();
59             }
60             ulong cpuCycles = GetCycleCount() - cycleCount;
61             watch.Stop();
62 
63             // 4.恢复控制台默认前景色,并打印出消耗时间及CPU时钟周期
64             Console.ForegroundColor = currentForeColor;
65             Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
66             Console.WriteLine("\tCPU Cycles:\t" + cpuCycles.ToString("N0"));
67 
68             // 5.打印执行过程中各代垃圾收集回收次数
69             for (int i = 0; i <= GC.MaxGeneration; i++)
70             {
71                 int count = GC.CollectionCount(i) - gcCounts[i];
72                 Console.WriteLine("\tGen " + i + ": \t\t" + count);
73             }
74 
75             Console.WriteLine();
76         }
77 
78         private static ulong GetCycleCount()
79         {
80             ulong cycleCount = 0;
81             QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
82             return cycleCount;
83         }
84 
85         [DllImport("kernel32.dll")]
86         [return: MarshalAs(UnmanagedType.Bool)]
87         static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);
88 
89         [DllImport("kernel32.dll")]
90         static extern IntPtr GetCurrentThread();
91     }
92 }
View Code

参考文章:

一个简单的性能计数器:CodeTimer

posted on 2015-04-23 12:38  永远的麦子  阅读(1852)  评论(2编辑  收藏  举报