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

    早上看到老赵写的这个性能计数器,感觉很实用,不过老赵用了很多.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.Linq;
using System.Text;

using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeTimer.Time("Thread Sleep",1,new TestSleep3000());
            CodeTimer.Time("Empty Method",1000000,new TestEmptyMethod());
            CodeTimer.Time("String Concat",100000,new TestStringConcat());
            CodeTimer.Time("StringBuilder Concat",100000,new TestStringBuilderConcat());

            //采用委托测试
            //CodeTimer.Time("Thread Sleep",1,delegate(){Thread.Sleep(3000);});
            //CodeTimer.Time("Empty Method",1000000,delegate(){});
            //string a="";
            //CodeTimer.Time("String Concat",100000,delegate(){a+="a";});
            //StringBuilder s=new StringBuilder();
            //CodeTimer.Time("StringBuilder Concat",100000,delegate(){s.Append("a");});

        }
    }

    public static class CodeTimer
    {
        public static void Initialize()
        {
            Process.GetCurrentProcess().PriorityClass=ProcessPriorityClass.High;
            Thread.CurrentThread.Priority=ThreadPriority.Highest;
            Time("",1,()=>{ });
        }

         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();
        }


        [DllImport("kernel32.dll",SetLastError=true)]
        [return:MarshalAs(UnmanagedType.Bool)]
        static extern   bool GetThreadTimes(IntPtr threadHandle,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,userTime;
            GetThreadTimes(GetCurrentThread(),out l,out l,out kernelTime,out userTime);
            return kernelTime+userTime;
        }

        static CodeTimer()
        {
            Process.GetCurrentProcess().PriorityClass=ProcessPriorityClass.High;
            Thread.CurrentThread.Priority=ThreadPriority.Highest;
        }
    }
    public interface IAction
    {
        void Action();
    }
    public class TestSleep3000:IAction
    {

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

    public class TestEmptyMethod : IAction
    {
        public void Action()
        {
            
        }
    }

    public class TestStringConcat : IAction
    {
        string s="";
        public void Action()
        {
            s+="a";
        }
    }

    public class TestStringBuilderConcat : IAction
    {
        StringBuilder s=new StringBuilder();
        public void Action()
        {
            s.Append("a");
        }
    }

   
}


运行结果如图:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值