我知道这是一个老问题,但只是添加一些经验数据......
在包含 10,000 个条目的字典上运行 50,000,000 次查找并比较完成的相对时间:
..如果每次查找都成功:
- 直接(未经检查)运行需要 1.2 秒
- 受保护的 (ContainsKey) 运行需要 2 秒
- 处理(try-catch)运行需要 1.21 秒
..如果每 10,000 次查找中有 1 次失败:
- 受保护的 (ContainsKey) 运行需要 2 秒
- 处理(try-catch)运行需要 1.37 秒
..如果每 10,000 次查找中有 16 次失败:
- 受保护的 (ContainsKey) 运行需要 2 秒
- 处理(try-catch)运行需要 3.27 秒
..如果每 10,000 次查找中有 250 次失败:
- 受保护的 (ContainsKey) 运行需要 2 秒
- 处理(try-catch)运行需要 32 秒
..因此,受保护的测试将增加恒定的开销,仅此而已,并且如果它从不失败,try-catch 测试的运行速度几乎与没有测试一样快,但会与失败的数量成比例地降低性能。
我用来运行测试的代码:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{ Test(0);
Test(1);
Test(16);
Test(250);
}
private static void Test(int failsPerSet)
{ Dictionary<int, bool> items = new Dictionary<int,bool>();
for(int i = 0; i < 10000; i++)
if(i >= failsPerSet)
items[i] = true;
if(failsPerSet == 0)
RawLookup(items, failsPerSet);
GuardedLookup(items, failsPerSet);
CaughtLookup(items, failsPerSet);
}
private static void RawLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Raw (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void GuardedLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Guarded (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
if(items.ContainsKey(pick))
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void CaughtLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Caught (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
try
{ if(items[pick])
found++;
}
catch
{
}
}
Console.WriteLine(DateTime.Now - start);
}
}
}