C# 在.NET4中出现这种巨大性能差异的原因是什么
我只是在研究红黑树。我知道.NET4.0中的SortedSet类使用红黑树。因此,我使用Reflector将该部分按原样取出,并创建了一个RedBlackTree类。现在,我正在这个RedBlackTree和SortedSet上运行一些性能测试,插入40000个顺序积分值(从0到39999),我惊讶地发现有巨大的性能差异,如下所示:C# 在.NET4中出现这种巨大性能差异的原因是什么,c#,.net,data-structures,performance,red-black-tree,C#,.net,Data Structures,Performance,Red Black Tree,我只是在研究红黑树。我知道.NET4.0中的SortedSet类使用红黑树。因此,我使用Reflector将该部分按原样取出,并创建了一个RedBlackTree类。现在,我正在这个RedBlackTree和SortedSet上运行一些性能测试,插入40000个顺序积分值(从0到39999),我惊讶地发现有巨大的性能差异,如下所示: RBTree took 9.27208 sec to insert 40000 values SortedSet took 0.0253097 se
RBTree took 9.27208 sec to insert 40000 values
SortedSet took 0.0253097 sec to insert 40000 values
背后的原因是什么?顺便说一句,我只在版本配置中运行了测试,下面是小测试代码
var stopWatch = new Stopwatch();
var rbT = new RedBlackTree<int>();
stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 40000; i++) {
rbT.Add(i);
}
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
var ss = new SortedSet<int>();
stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 40000; i++) {
ss.Add(i);
}
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
RBTree与上述相同(从SortedSet类中剥离)我也尝试了400000个值,但是RBTree似乎花了很长时间,我真的不知道为什么。如果差异没有那么大,我建议原因是.NET程序集是NGen-ed的,因此它们已经转换为本机代码。在您的类中,将IL代码编译成本机代码的时间在您的测试期间进行摊销。增加循环迭代次数如何影响时间?SortedSet包含一个属性,您复制的版本是否包含该属性
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public bool Add(T item)
{
return this.AddIfNotPresent(item);
}
您的
节点
类中有一个bug。当调用仅接受单个值参数的构造函数时,应将IsRed
设置为true
我假设fixed节点
类应该如下所示:
public sealed class Node<T>
{
public T Item { get; private set; }
public bool IsRed { get; set; }
public Node<T> Left { get; set; }
public Node<T> Right { get; set; }
public Node(T value)
{
Item = value;
IsRed = true;
}
public Node(T value, bool isRed)
{
Item = value;
IsRed = isRed;
}
}
然后在Add
方法中替换这一行
Node<T> current = new Node<T>(item);
节点当前=新节点(项目);
…用这个
Node<T> current = new Node<T>(item, true);
Node current=新节点(项,true);
您是否尝试过使用探查器找出代码花费最多时间的位置?当您说您在版本配置中“运行”测试时,是在调试器中吗?或者在平面命令提示符下?如果代码以相反的顺序执行(例如先执行SortedSet,然后执行RBTree),是否仍会发生这种情况?我怀疑是JIT。按照ChrisBD所说的相反顺序运行它,或者运行几次,而不仅仅是一次(我的意思是将代码放入一个循环中,以便它在同一个程序执行中运行几次)@Choco,如果JIT需要9秒,我们就不会使用它。NETIt与性能无关。从MSDN开始,它表明应用此属性的.NET Framework类库方法不太可能受服务版本的影响,因此有资格跨本机映像生成器(NGen)映像内联。我怀疑性能差异是由于跨本机映像生成器(NGen)的方法内联造成的图像。@Anindya Chatterjee-这些方法很小,因此内联它们可以在性能中发挥重要作用。你说得对!随机化数据会给出可比较的结果。性能差异可以忽略不计。但我说的是最坏的情况。为什么在这种特殊情况下,这两种算法在SortedList由RBTree本身实现的情况下表现不同?所以它们是两种完全不同的算法。又是一场追逐。噢!你就是那个人。我刚刚更改了它并运行了诊断,猜测对于同一组数据,现在的响应时间是-00.0204438秒。谢谢你,伙计,你拯救了这一天。太棒了。包括我在内的很多人都在猜测NGen、反向顺序、编译问题。。。它似乎来自代码:)在这种情况下,很难指出。更便宜的(最好的选择)总是与环境相关的。但是IMO首先应该检查代码,以防出现如此惊人的性能差异或其他类型的完全出乎意料的结果。我也有过类似的经历,在代码和纠正代码的问题上,我总能把事情做好!!这也是Occam剃刀原理的一个很好的例子。它指出,在相互竞争的假设中,应选择假设最少的假设
public sealed class Node<T>
{
public T Item { get; private set; }
public bool IsRed { get; set; }
public Node<T> Left { get; set; }
public Node<T> Right { get; set; }
public Node(T value, bool isRed)
{
Item = value;
IsRed = isRed;
}
}
Node<T> current = new Node<T>(item);
Node<T> current = new Node<T>(item, true);