这篇文章给大家分享的是有关如何实现C#扩展方法性能测试的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
C#扩展方法性能测试方法三则
一共是如下三个方法与string.IsNullOrEmpty(称为“原方法”)比较:
//扩展方法 public static bool IsNullOrEmpty1(this string s) { return string.IsNullOrEmpty(s); } //手工方法 public static bool IsNullOrEmpty2(string s) { return s == null || s == string.Empty; } //lambda方法 public static Func< string, bool> IsNullOrEmpty3 = s => string.IsNullOrEmpty(s);
我们在函数名后面添加上一个数字,将它们区分开,以避免相互混淆。
为了测试公正,尽量消除测试中的误差,我们采用一个数组存放要测试的字符串。
这个数组中存放三种字符串,非Empty非Null、Empty、Null。随机存入,数量大致相同。生成算法如下:
private static string[] GetTestStringArray(int count) { string[] result = new string[count]; Random random = new Random(); int r = 0; for (int i = 0; i < count; i++) { r = random.Next(3); if (r == 0) result[i] = i.ToString(); else if (r == 1) result[i] = string.Empty; else result[i] = null; } return result;
我们让这四个算法(前面三个算法+原来的静态算法)依次对数组中的每一项进行判断。
有一点要特别注意,对集合遍历也要耗时,我们要排除这段时间。
下面给出测试算法,写的不好,别见笑:
public static void Test() { int count = 10000000; //7个零 string[] ss = GetTestStringArray(count); //测试字符串Array bool b; string str; long t = 0; //基本循环时间 long t0 = 0; //原方法时间 long t1 = 0; //扩展方法时间 long t2 = 0; //手工方法时间 long t3 = 0; //lambda时间 Stopwatch watch = new Stopwatch(); for (int i = 0; i < 10; i++) //循环测试10次 { watch.Reset(); watch.Start(); foreach (string s in ss) str = s; watch.Stop(); Console.Write("基本循环:" + watch.ElapsedMilliseconds + "ms\t\t\t\t"); t += watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); foreach (string s in ss) { str = s; b = string.IsNullOrEmpty(str); } watch.Stop(); Console.Write("原方法:" + watch.ElapsedMilliseconds + "ms\t\t"); t0 += watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); foreach (string s in ss) { str = s; b = str.IsNullOrEmpty1(); } watch.Stop(); Console.Write("扩展方法:" + watch.ElapsedMilliseconds + "ms\t\t"); t1 += watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); foreach (string s in ss) { str = s; b = IsNullOrEmpty2(str); } watch.Stop(); Console.Write("手工方法:" + watch.ElapsedMilliseconds + "ms\t\t"); t2 += watch.ElapsedMilliseconds; watch.Reset(); watch.Start(); foreach (string s in ss) { str = s; b = IsNullOrEmpty3(str); } watch.Stop(); Console.Write("lambda方法:" + watch.ElapsedMilliseconds + "ms\t\t"); t3 += watch.ElapsedMilliseconds; Console.WriteLine(); } Console.WriteLine(); Console.WriteLine(string.Format("扩展方法\t / 原方法\t = {0:f2}", (t1 - t) * 1.0 / (t0 - t))); Console.WriteLine(string.Format("手工方法\t / 原方法\t = {0:f2}", (t2 - t) * 1.0 / (t0 - t))); Console.WriteLine(string.Format("lambda方法\t / 原方法\t = {0:f2}", (t3 - t) * 1.0 / (t0 - t))); }
想重构一下,考虑了几种办法,不太好,怕重构后大家看起来更费力。
Test中的4个小段代码很相似,分别用来测量4个算法的用时。
1 foreach (string s in ss) str = s;
上面这句代码是基本循环,后面三组代码都在它基础上加入相应操作。
Test()不复杂,就是太啰嗦,大家都看得明白。
先在Debug模式下执行测试:
后面三个方法效率也太低了吧!!且一放,再看Release模式:
比前面效率提高了一些。***是把Release模式下生成的程序,放在命令行中执行:
说明一:项目的输出类型必需是“控制台应用程序”才能在控制台中输出。
说明二:控制台的宽度比较小,我删除了Test()中输出中的几个制表符等,才让它输入不换行。
说明三:本处执行的是Release模式生成的程序,而不是Debug模式生成的程序。
Debug和Release测试是在VS2008宿主中进行的,***控制台测试才是真正的实际运行环境,我们测试结果以控制台测试结果为准。
之所以将前面两个贴出来,是告诉大家在vs中调试测试的结果是相当不准确的。
C#扩展方法性能测试结果
我们来分析下测试的结果吧:
扩展方法的效率是相当高的,与原方法只有百分之几(多运行几次,可能是1、3、4甚至0,还有一次是-2,即比值为0.98)的性能损失。
手工方法效率***,低得出乎大多数人的意料。
lambda会带来“可观”的性能损失。
如果考虑性能:可以使用扩展方法,但扩展方法内部不要使用lambda表达式,其内部尽量使用常规代码。
(其实扩展方法内部代码简洁与否无所谓,毕竟扩展方法是一种封装,可以将内部复杂的操作隐藏起来并以一个简单的扩展方法提供给调用者)
如果考虑性能:少用lambda,多用原生方法。
感觉:这次测试的结果令我倍感意外,确实没想到c#扩展方法的效率如此之高(看来我的扩展想法有市场了)!
期望:本人是“粗人”,很不细心,大家如果发现上面测试中有错误,请马上告知我,谢谢!
打算:对一个c#扩展方法的测试说服力不够,以后会再做一些相关测试工作。
感慨:效率的高低不是眼睛看看、脑子想想能断定的,而必需采用科学的测试方法才可以给出结论。
感谢各位的阅读!关于“如何实现C#扩展方法性能测试”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!