浅测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模式影响到.但具体影响的大不大就请高手告知我一声,而完成了这篇代码之后我还有其他正式得干呢,呵呵.
