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

早上看到老赵写的这个性能计数器,感觉很实用,不过老赵用了很多.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", 1, new TestSleep3000()); CodeTimer.Time("Thread Sleep", 10000000, new TestEmptyMethod()); CodeTimer.Time("String Concat", 100000, new 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", 1, delegate() { Thread.Sleep(3000); }); CodeTimer.Time("Empty Method", 10000000, delegate() { }); string a = ""; CodeTimer.Time("String Concat", 100000, delegate() { a += "a"; }); StringBuilder s = new StringBuilder(); CodeTimer.Time("StringBuilder Conca", 100000, delegate() { 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值