jay*_*noh 0 .net c# linq clr performance
我突然对linq性能感到好奇,并进行了一些测试.
下面是我的测试代码,结果非常令人惊讶.
任何人都可以使用linq工作,为什么比TryOut慢?
Public class TestObject
{
....
....
//this class contain many members
bool deleted;
....
}
class Program
{
public static ConcurrentDictionary<string, TestObject> testDictionary = new ConcurrentDictionary<string, TestObject>();
static void Main(string[] args)
{
//testDictionary is initialized in ohter code and is likely to have 10000 elements.
RandomTest(0);
RandomTest(1);
Console.ReadKey();
}
static void RandomTest(int k)
{
int count = 10000;
List<string> randomId = new List<string>();
Random rnd = new Random();
for (int i = 0; i < count; i++)
{
int randomNumber = rnd.Next(0, testDictionary.Count());
randomId.Add(testDictionary.ElementAt(randomNumber).key);
}
Stopwatch sw = new Stopwatch();
sw.Start();
if (k == 0)
{
for (int i = 0; i < count; i++)
{
var res = checkid(randomId[i]);
}
}
else if (k == 1)
{
for (int i = 0; i < count; i++)
{
var res = checkid2(randomId[i]);
}
}
sw.Stop();
Console.WriteLine("Elapsed time : " + sw.Elapsed);
}
static bool checkid(string id)
{
TestObject t;
return !testDictionary.TryGetValue(id, out t) ?
false : t.deleted ?
false : true;
}
static bool checkid2(string id)
{
return testDictionary.Any(t => t.key == id && !t.Value.deleted)? true : false;
}
Run Code Online (Sandbox Code Playgroud)
我运行了这两个方法10000次,结果显示如下
对于checkid方法,它大多花了不到00:00:00.002.
对于checkid2方法,它主要在00:00:02.2和00:00:02.4之间进行.
这是一个巨大的差异.
这是因为checkid2方法也检查已删除的变量,即使key不等于Id,而checkid方法只有在找到相应的密钥时检查已删除的变量?
Dictionary.TryGetValue正在使用散列来定位元素,因此它是一个O(1)操作.
Dictionary.Any将遍历集合,试图找到一个匹配条件的集合.那是O(n).
一般来说 - LINQ比使用for/ 的手工制作循环要慢一点foreach,但在大多数情况下性能差异并不重要.你所经历的不是LINQ在这里很慢,它的Dictionary<T>.TryGetValue速度很快,因为它的内部结构被优化用于基于密钥的搜索.如果你改变它确实是一个List<T>并写一个for循环来以线性方式进行相同的搜索(就像LINQ一样)你会看到差异变小了.
| 归档时间: |
|
| 查看次数: |
325 次 |
| 最近记录: |