在C#里,要测试一段代码的性能,尤其是在时间方面的性能,最常用的方法就是给代码添加计时功能啦!比如以下一段代码:
static void Test1()
{
long sum = 0;
for (int i = 0; i < 100000000; i++)
{
sum += 1;
}
Console.WriteLine(sum);
}
可在调用这个方法时在其前后加两个DateTime的实例
DateTime time1 = DateTime.Now;
DateTime time2 = DateTime.Now;
最后两者想减得时间差。
这是一种常用的方法,还有一种就是:
Stopwatch watch = new Stopwatch();(PS:需添加引用using System.Diagnostics;)
watch.Start()和watch.Stop()分别用于开始计时和停止计时,最后
watch.ElapsedMilliseconds获取总共用时,单位为毫秒。
以下是两种的测试用法:
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TimeTest
{
class Program
{
static void Main(string[] args)
{
Test1();
Console.ReadKey();
}
static void Test()
{
long sum = 0;
for (int i = 0; i < 100000000; i++)
{
sum += 1;
}
Console.WriteLine(sum);
}
public static void Test1()
{
DateTime time1 = DateTime.Now;
Test();
DateTime time2 = DateTime.Now;
Console.WriteLine((time2 - time1).TotalMilliseconds);
Stopwatch watch = new Stopwatch();
watch.Start();
Test();
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
}
}
}
至于两者的结果有区别,这个将在后面说到。
然而,每次编译运行这段代码时,前者的波动较大,后者波动较小,不过两者相差不大。
虽然这两种方式对执行时间的测试好像都还行,只要大体了解一下代码的执行时间即可。然而,在.NET环境下运行时间代码时完全不合适的,为什么呢?
首先,代码测量的是从子程序调用到子程序返回主程序之间所用的时间,但是测试所测量的时间也包含了与C#程序同时运行的其他进程所用的时间。
其次,时间代码没有考虑.NET环境下执行的无用单元收集(PS:在C#中也称为垃圾收集或垃圾回收)。在类似的.NET这样的运行时间环境中,系统可能在执行诶用单元收集的任何一个时间暂停。时间代码示例没有考虑无用单元收集,结果时间很容易受到无用单元收集的影响。那么到底该怎么做呢?
在.NET框架下通过使用Process类可以做到。Process类拥有的方法允许选取当前的进程(程序允许其内的进程)、选取程序运行其内的进程,以及选取存储线程开始执行时间的计时器。这些方法中的每一个都可以合并成一个调用,此调用会把它的返回值赋给一个变量用来存储开始时间(TimeSpan对象)。如下代码
TimeSpan startTime=Process.GetCurrentProcess().Threads[0].UserProcessorTime;
剩下要做的事就是在进行时间测试的代码段停止时捕获时间。做法如下:
TimeSpan endTime = Process.GetCurrentProcess().Threads[0].TotalProcessorTime;
Console.WriteLine((endTime-startTime).TotalMilliseconds);
现在把这些合并为一个程序,此程序的代码和先前的测试代码一样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TimeTest
{
class Program
{
static void Main(string[] args)
{
Test2();
Console.ReadKey();
}
static void Test()
{
long sum = 0;
for (int i = 0; i < 100000000; i++)
{
sum += 1;
}
Console.WriteLine(sum);
}
public static void Test2()
{
TimeSpan startTime = Process.GetCurrentProcess().Threads[0].UserProcessorTime;
Test();
TimeSpan endTime = Process.GetCurrentProcess().Threads[0].TotalProcessorTime;
Console.WriteLine((endTime-startTime).TotalMilliseconds);
}
}
}
采样新改进的时间测试代码后,测试代码段的完成时间为:156.001毫秒,相比为之前测试的十分之一左右。很明显,这两种时间测试方法之间存在着显著差异。
因而.NET环境中的时间测试代码应该使用.NET方法来做。