• 如何计算代码的运行性能


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

    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("	Time Elapsed:	" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
    66             Console.WriteLine("	CPU Cycles:	" + 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("	Gen " + i + ": 		" + 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

  • 相关阅读:
    解锁 redis 锁的正确姿势
    PHP实现Redis单据锁,防止并发重复写入
    js笔记
    FormData使用方法详解
    jquery里用each遍历的值存到数组和字符串
    Sublime Text3 安装 CTags 插件出现乱码
    通过pd.to_sql()将DataFrame写入Mysql
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket
    pandas 从txt读取DataFrame&DataFrame格式化保存到txt
    pandas 取消读取csv时默认第一行为列名
  • 原文地址:https://www.cnblogs.com/mcgrady/p/4448096.html
Copyright © 2020-2023  润新知