{ Snake @ NET } 废寝忘食的程序工作者.

18三/100

浅测Try&Catch的性能到底有多差(3)

Hello,我是Snake,欢迎阅读我的文章--浅测Try&Catch的性能到底有多差(3)

上2节咱们使用30000行杨辉三角来测试try&catch的性能,结果差强人意.原因是什么我不是很确定,但是有一点我觉得有点问题,而且结果很有可能就差在这上面:我们无法确定try块被执行了多少次,catch块被执行了多少次.当然算是能算,就是太麻烦.而这次我把算法设定的很简单.代码如下:

using System;
using System.Diagnostics;

public class MyClass
{
	public static void Main()
	{
		string[] strs=
		{
			"I'm",
			"Snake"
		};
		int rounds=1000000;
		Stopwatch sw=new Stopwatch();
		for(int r=0;r<5;r++)
		{
			sw.Reset();
			sw.Start();
			for(int i=0;i<rounds;i++)
			{
				string s=strs[i%2];

				if(s.Length>5)
					s.Substring(3,1);
				else
					s.Substring(0,1);
				/*
				try
				{
					s.Substring(3,1);
				}
				catch
				{
					s.Substring(0,1);
				}
				*/
			}
			sw.Stop();
			Console.WriteLine(sw.ElapsedMilliseconds);
		}
		Console.ReadLine();
}
}

这个算法优点是不占内存,另外使用了引用类型的简单操作.,并且我们可以知道算法中各个块被执行了多少次.
这次我毫不留情地把基数(即:rounds)设定得很大,达到一百万.那么我们的if&else还有块在这个算法中执行了多少次呢?

循环次数:1,000,000
if块: 1,000,000次
else块 500,000次
try块 1,000,000次
catch块 500,000次

好的,让我们来看看运行结果吧!

If&Else
1. 40ms
2. 39ms
3. 37ms
4. 37ms
5. 40ms
6. 38ms
7. 37ms
8. 37ms
9. 37ms
10. 39ms
平均值:38.1 ms

Try&Catch
1. 39947ms
2. 39744ms
3. 39054ms
4. 39971ms
5. 40006ms
然后我实在等不下去了…于是中止了10次循环.
好吧,性能差了整整1000倍.
这次再改改代码,事先说一下,这次改代码是出于个人兴趣,比较一下引用类型和值类型的性能,跟本主题无关.
更改代码如下:

int[] ints={0,1};
int rounds=1000000;
for(int i=0;i<rounds;i++)
{
	int n=ints[i%2];

	if(n>0)
		n = n/2;
	else
		n = n+1/2;
}

运行结果是清一色的1ms.感叹一下值类型的操作果然比引用类型快,那么题外话就赶快结束吧.

回到我们之前操作string的代码中,我们这次的代码修改如下:

public class MyClass
{
	public static void Main()
	{
		string str="Hi";
		int rounds=1000000;
		Stopwatch sw=new Stopwatch();
		for(int r=0;r<10;r++)
		{
			sw.Reset();
			sw.Start();
			for(int i=0;i<rounds;i++)
			{

				if(str.Length>5)
					str.Substring(3,1);
				else
					str.Substring(0,1);
				/*
				try
				{
					s.Substring(3,1);
				}
				catch
				{
					s.Substring(0,1);
				}
				*/
			}
			sw.Stop();
			Console.WriteLine(sw.ElapsedMilliseconds);
		}
		Console.ReadLine();
	}
}

这次的执行次数如下:
循环次数:1,000,000
if块: 1,000,000次
else块 1,000,000次
try块 1,000,000次
catch块 1,000,000次

运行结果如下:

if&else运行10次结果如下:
1. 37 ms
2. 36 ms
3. 37 ms
4. 36 ms
5. 36 ms
6. 36 ms
7. 36 ms
8. 40 ms
9. 36 ms
10. 36 ms
见鬼,比之前的还快= =

那么轮到测试try&catch块了:
1. 85498ms
2. 84335ms
我不想再测试了.这次性能更可怕了.原来try块跟catch块都有性能消耗.那finally块呢?我们来验证一下吧!
加上finally以后,耗时还是85ms左右.那就不让catch块执行看看执行时间有什么变化呢.
结果竟然和if&else一样的37ms!

本节总结:

根据上面的分析,特别是文章末尾的分析非常明显的表明了如果在try块中执行无误的代码的性能损失几乎为0,但是一旦try块中的代码出现错误,那么CLR(应该是这玩意)就会生成一个异常,并且进入catch块中.catch块中搞了什么鬼我不知道,也暂时没能力知道,但是最终倒是让我明白了原来罪魁祸首是出了错的try块中的代码导致运行catch才出现的性能损耗.
最后我要说个前两节都忘记说的事:我是用Snippet Compiler编写并执行所有的代码的,而据说Snippet Compiler是以debug的形式执行的代码.所以所有之前的代码性能可能会被debug模式影响到.但具体影响的大不大就请高手告知我一声,而完成了这篇代码之后我还有其他正式得干呢,呵呵.

Snake @ NET

站内任何内容未经作者声明,皆为作者原创,并采用知识共享署名2.5中国大陆许可协议Creative Commons License进行许可.

欢迎转载,但转载者必须提供以下文字和连接:

喜欢这个文章吗?

考虑订阅我们的RSS Feed吧!

评论 (0) 引用 (0)

还没有评论.


发表评论


还没有引用.