• 对老赵写的简单性能计数器的修改


    对老赵写的简单性能计数器的修改

        早上看到老赵写的这个性能计数器,感觉很实用,不过老赵用了很多.C# 3.0 的新语法,还用了 VISTA 和 Server 2008 下特有的Win32 API,对于还在用C#2.0 或者还工作在 XP 或者 Server 2003 下的兄弟们,只能望代码心叹了。应老赵的要求,我修改了他的代码,增加了对低版本C# 和 低版本windows 操作系统的支持。

        老赵的原文: 一个简单的性能计数器:CodeTimer

        修改说明

        1. 采用 接口 取代了原代码中的 Lambda 表达式

        2. 采用 GetThreadTimes 这个API 函数替代了原代码中的 QueryThreadCycleTime

        这里需要说明的是 GetThreadTimes 给出了线程在内核态和用户态占用的时间,单位是 100 ns。两个时间的总和就是线程占用的CPU时间。这个API的时间精度我看了一些资料似乎没有达到 100ns. 所以GetThreadTimes 这个API函数的进度没有 QueryThreadCycleTime 高。

        下面是我修改后的代码

        注释1: 2009-03-11 增加委托的调用,修改 GC.Collect 参数,兼容.Net 2.0.  增加每次调用时间统计 

        增加了委托调用后,我发现同样是测试空函数,采用接口比采用委托效率要略高一些,这和我的预计基本吻合,因为委托不是单纯的函数调用,具体原理超出本文范围,我就不多说了。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;
    using System.Threading;
    using System.Runtime.InteropServices;
      
     
        
    public interface IAction
        
    {
            
    void Action();
        }


        
    public static class CodeTimer
        
    {
            [DllImport(
    "kernel32.dll", SetLastError = true)]
            
    static extern bool GetThreadTimes(IntPtr hThread, out long lpCreationTime,
               
    out long lpExitTime, out long lpKernelTime, out long lpUserTime);

            [DllImport(
    "kernel32.dll")]
            
    static extern IntPtr GetCurrentThread();

            
    public delegate void ActionDelegate();

            
    private static long GetCurrentThreadTimes()
            
    {
                
    long l;
                
    long kernelTime, userTimer;
                GetThreadTimes(GetCurrentThread(), 
    out l, out l, out kernelTime, 
                   
    out userTimer);
                
    return kernelTime + userTimer;
            }


            
    static CodeTimer()
            
    {
                Process.GetCurrentProcess().PriorityClass 
    = ProcessPriorityClass.High;
                Thread.CurrentThread.Priority 
    = ThreadPriority.Highest;

            }


            
    public static void Time(string name, int iteration, ActionDelegate action)
            
    {
                
    if (String.IsNullOrEmpty(name))
                
    {
                    
    return;
                }


                
    if (action == null)
                
    {
                    
    return;
                }


                
    //1. Print name
                ConsoleColor currentForeColor = Console.ForegroundColor;
                Console.ForegroundColor 
    = ConsoleColor.Yellow;
                Console.WriteLine(name);


                
    // 2. Record the latest GC counts
                
    //GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
                GC.Collect(GC.MaxGeneration);
                
    int[] gcCounts = new int[GC.MaxGeneration + 1];
                
    for (int i = 0; i <= GC.MaxGeneration; i++)
                
    {
                    gcCounts[i] 
    = GC.CollectionCount(i);
                }


                
    // 3. Run action
                Stopwatch watch = new Stopwatch();
                watch.Start();
                
    long ticksFst = GetCurrentThreadTimes(); //100 nanosecond one tick

                
    for (int i = 0; i < iteration; i++) action();
                
    long ticks = GetCurrentThreadTimes() - ticksFst;
                watch.Stop();

                
    // 4. Print CPU
                Console.ForegroundColor = currentForeColor;
                Console.WriteLine(
    "\tTime Elapsed:\t\t" + 
                   watch.ElapsedMilliseconds.ToString(
    "N0"+ "ms");
                Console.WriteLine(
    "\tTime Elapsed (one time):" + 
                   (watch.ElapsedMilliseconds 
    / iteration).ToString("N0"+ "ms");

                Console.WriteLine(
    "\tCPU time:\t\t" + (ticks * 100).ToString("N0"
                   
    + "ns");
                Console.WriteLine(
    "\tCPU time (one time):\t" + (ticks * 100 / 
                   iteration).ToString(
    "N0"+ "ns");

                
    // 5. Print GC
                for (int i = 0; i <= GC.MaxGeneration; i++)
                
    {
                    
    int count = GC.CollectionCount(i) - gcCounts[i];
                    Console.WriteLine(
    "\tGen " + i + ": \t\t\t" + count);
                }


                Console.WriteLine();

            }


            
    public static void Time(string name, int iteration, IAction action)
            
    {
                
    if (String.IsNullOrEmpty(name))
                
    {
                    
    return;
                }


                
    if (action == null)
                
    {
                    
    return;
                }


                
    //1. Print name
                ConsoleColor currentForeColor = Console.ForegroundColor;
                Console.ForegroundColor 
    = ConsoleColor.Yellow;
                Console.WriteLine(name);


                
    // 2. Record the latest GC counts
                
    //GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
                GC.Collect(GC.MaxGeneration);
                
    int[] gcCounts = new int[GC.MaxGeneration + 1];
                
    for (int i = 0; i <= GC.MaxGeneration; i++)
                
    {
                    gcCounts[i] 
    = GC.CollectionCount(i);
                }


                
    // 3. Run action
                Stopwatch watch = new Stopwatch();
                watch.Start();
                
    long ticksFst = GetCurrentThreadTimes(); //100 nanosecond one tick
                
                
    for (int i = 0; i < iteration; i++) action.Action();
                
    long ticks = GetCurrentThreadTimes() - ticksFst;
                watch.Stop();

                
    // 4. Print CPU
                Console.ForegroundColor = currentForeColor;
                Console.WriteLine(
    "\tTime Elapsed:\t\t" + 
                   watch.ElapsedMilliseconds.ToString(
    "N0"+ "ms");
                Console.WriteLine(
    "\tTime Elapsed (one time):" + 
                   (watch.ElapsedMilliseconds 
    / iteration).ToString("N0"+ "ms");

                Console.WriteLine(
    "\tCPU time:\t\t" + (ticks * 100).ToString("N0"
                    
    + "ns");
                Console.WriteLine(
    "\tCPU time (one time):\t" + (ticks * 100 / 
                    iteration).ToString(
    "N0"+ "ns");

                
    // 5. Print GC
                for (int i = 0; i <= GC.MaxGeneration; i++)
                
    {
                    
    int count = GC.CollectionCount(i) - gcCounts[i];
                    Console.WriteLine(
    "\tGen " + i + ": \t\t\t" + count);
                }


                Console.WriteLine();

            }

        }

       

    测试类

        public class TestSleep3000 : IAction
        {
            
    #region IAction Members

            
    public void Action()
            {
                Thread.Sleep(
    3000);
            }

            
    #endregion
        }


        
    public class TestEmptyMethod : IAction
        {
            
    #region IAction Members

            
    public void Action()
            {
            }

            
    #endregion
        }

        
    public class TestStringConcat : IAction
        {
            
    string s = "";

            
    #region IAction Members

            
    public void Action()
            {
                s 
    += "a";
            }

            
    #endregion
        }

        
    public class TestStringBuilderConcat : IAction
        {
            StringBuilder s 
    = new StringBuilder();

            
    #region IAction Members

            
    public void Action()
            {
                s.Append (
    "a");
            }

            
    #endregion
        }

    测试代码

    采用接口 

                CodeTimer.Time("Thread Sleep"1new TestSleep3000());
                CodeTimer.Time(
    "Thread Sleep"10000000new TestEmptyMethod());
                CodeTimer.Time(
    "String Concat"100000new TestStringConcat());
                CodeTimer.Time(
    "StringBuilder Conca"100000
                     
    new TestStringBuilderConcat()); 

    测试结果

    Thread Sleep
            Time Elapsed:           2,997ms
            Time Elapsed (one time):2,997ms
            CPU time:               0ns
            CPU time (one time):    0ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

    Empty Method
            Time Elapsed:           138ms
            Time Elapsed (one time):0ms
            CPU time:               125,000,000ns
            CPU time (one time):    12ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

    String Concat
            Time Elapsed:           10,547ms
            Time Elapsed (one time):0ms
            CPU time:               10,546,875,000ns
            CPU time (one time):    105,468ns
            Gen 0:                  4102
            Gen 1:                  2661
            Gen 2:                  2545

    StringBuilder Conca
            Time Elapsed:           4ms
            Time Elapsed (one time):0ms
            CPU time:               0ns
            CPU time (one time):    0ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

    采用委托

    CodeTimer.Time("Thread Sleep"1delegate() { Thread.Sleep(3000); });
    CodeTimer.Time(
    "Empty Method"10000000delegate() { });

    string a = "";

    CodeTimer.Time(
    "String Concat"100000delegate() { a += "a"; });

    StringBuilder s 
    = new StringBuilder();
    CodeTimer.Time(
    "StringBuilder Conca"100000delegate() { s.Append("a"); }); 

     测试结果

    Thread Sleep
            Time Elapsed:           2,989ms
            Time Elapsed (one time):2,989ms
            CPU time:               0ns
            CPU time (one time):    0ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

    Empty Method
            Time Elapsed:           156ms
            Time Elapsed (one time):0ms
            CPU time:               156,250,000ns
            CPU time (one time):    15ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

    String Concat
            Time Elapsed:           10,425ms
            Time Elapsed (one time):0ms
            CPU time:               10,406,250,000ns
            CPU time (one time):    104,062ns
            Gen 0:                  4102
            Gen 1:                  2661
            Gen 2:                  2545

    StringBuilder Conca
            Time Elapsed:           4ms
            Time Elapsed (one time):0ms
            CPU time:               0ns
            CPU time (one time):    0ns
            Gen 0:                  0
            Gen 1:                  0
            Gen 2:                  0

  • 相关阅读:
    忽略大小写的RegularExpressionValidator
    Outlook 2010 “加载项执行错误。调用“Microsoft Exchange 加载项”加载项时,在“IDTExtensibility2”接口回调“OnConnection”期间,Outlook 出现故障”问题
    选择排序——算法系列
    代码杂记32
    数据库系统原理
    C#中的委托与事件
    C#多线程
    冒泡排序——算法系列
    快速排序——算法系列
    递归算法——猴子吃桃
  • 原文地址:https://www.cnblogs.com/eaglet/p/1407791.html
Copyright © 2020-2023  润新知