您的位置:首页 > 其它

方法性能比较的好帮手:CodeTimer的扩展应用

2010-01-13 12:03 351 查看
09年的.NET技术大会上Jeffery Richard展示的性能测试代码中,功能强大的CodeTimer引起了大家的注意,由于Jeffery Richard还没有公布源码,于是园子里的老赵就自己写了一个,适用于在Console应用程序中输出性能测试的各个指标。

最近参与的项目中有很多想要进行方法性能比较的地方,于是就想起了这个CodeTimer,便狗尾续貂在老赵原有的代码上加上了一个Time方法的重载,以适用于非Console应用程序中快速的性能测试,比如Winform、Web、UnitTest、WindowsService等等。

修改后的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;

namespace PerformanceTest
{
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, Action action)
{
Time(name, iteration, action, Console.WriteLine);
}

public static void Time(string name, int iteration, Action action, Action<string> output)
{
if (String.IsNullOrEmpty(name)) return;

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

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

// 3.
Stopwatch watch = new Stopwatch();
watch.Start();
ulong cycleCount = GetCycleCount();
for (int i = 0; i < iteration; i++) action();
ulong cpuCycles = GetCycleCount() - cycleCount;
watch.Stop();

// 4.
Console.ForegroundColor = currentForeColor;
output("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
output("\tCPU Cycles:\t" + cpuCycles.ToString("N0"));

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

output(string.Empty);
}

private static ulong GetCycleCount()
{
ulong cycleCount = 0;
QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
return cycleCount;
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);

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



这样一来,就能够在Winform、Web、UnitTest、Service等各种应用程序中方便快捷的使用CodeTimer了,比如在Winform中的一个应用:



StringBuilder result;

private void button1_Click(object sender, EventArgs e)
{
string s = string.Empty;
PerformanceTest.CodeTimer.Time("String Concat", 10000, () => { s += "a"; }, Print);

StringBuilder sb = new StringBuilder();
PerformanceTest.CodeTimer.Time("StringBuilder", 10000, () => { sb.Append("a"); }, Print);

this.textBox1.Text = result.ToString();
}

void Print(string msg)
{
if (result == null)
result = new StringBuilder();
result.AppendLine(msg);
Console.WriteLine(msg);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: