Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在.NET4中出现这种巨大性能差异的原因是什么_C#_.net_Data Structures_Performance_Red Black Tree - Fatal编程技术网

C# 在.NET4中出现这种巨大性能差异的原因是什么

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

我只是在研究红黑树。我知道.NET4.0中的SortedSet类使用红黑树。因此,我使用Reflector将该部分按原样取出,并创建了一个RedBlackTree类。现在,我正在这个RedBlackTree和SortedSet上运行一些性能测试,插入40000个顺序积分值(从0到39999),我惊讶地发现有巨大的性能差异,如下所示:

 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);