LinkedList比List更快迭代?

时间:2014-01-23 18:19:56

标签: c# .net performance data-structures

出于某种原因,我的LinkedList似乎优于我的List。我有一个LinkedList,因为有一部分代码我必须重新安排孩子们。重新排列后的所有内容都只是循环数据并执行计算。我之前只是使用LinkedList迭代Iterator,但后来我认为我应该同时存储List相同的元素,以便我可以更快地迭代它们。不知何故,添加List并迭代它对于完全相同的事情来说明显更慢。不确定这是怎么回事,所以任何信息都有帮助。

以下是我希望更快的代码:

class Program {
    public static void Main(string[] args) {
        var originalList = new List<Thing>();
        for (var i = 0; i < 1000; i++) {
            var t = new Thing();
            t.x = 0d;
            t.y = 0d;
            originalList.Add(t);
        }
        var something = new Something(originalList);

        for (var i = 0; i < 1000; i++) {
            var start = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            something.iterate();
            time += (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - start;
            Console.Out.WriteLine(time / (i + 1));
        }
    }

    class Thing {
        public double x {get; set;}
        public double y {get; set;}
    }

    class Something {
                    private List<Thing> things;
        private LinkedList<Thing> things1 = new LinkedList<Thing>();
        private List<Thing> things2 = new List<Thing>();

        public Class(List<Thing> things) {
            this.things = things;

            for (var i = 0; i < things.Count; i++) {
                things1.AddLast(things[i]);
                things2.Add(things[i]);
            }
        }

        public void iterate() {
            //loops like this happen a few times, but the list is never changed, only the
            //objects properties in the list
            for (var i = 0; i < things2.Count; i++) {
                                    var thing = things2[i];
                thing.x += someDouble;
                thing.y += someOtherDouble;
            }
        }
    }
}

这是我第一次做的事情,我认为应该是SLOWER:

class Program {
    public static void Main(string[] args) {
        var originalList = new List<Thing>();
        for (var i = 0; i < 1000; i++) {
            var t = new Thing();
            t.x = 0d;
            t.y = 0d;
            originalList.Add(t);
        }
        var something = new Something(originalList);

        for (var i = 0; i < 1000; i++) {
            var start = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
            something.iterate();
            time += (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) - start;
            Console.Out.WriteLine(time / (i + 1));
        }
    }

    class Thing {
        public double x {get; set;}
        public double y {get; set;}
    }

    class Something {
        private List<Thing> things;
        private LinkedList<Thing> things1 = new LinkedList<Thing>();

        public Class(List<Thing> things) {
            this.things = things;

            for (var i = 0; i < things.Count; i++) {
                things1.AddLast(things[i]);
            }
        }

        public void iterate() {
            //loops like this happen a few times, but the list is never changed, only the
            //objects properties in the list
            var iterator = things1.First;
            while (iterator != null) {
                var value = iterator.Value;
                value.x += someDouble;
                value.y += someOtherDouble;
                iterator = iterator.Next;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:4)

很难验证任何东西,因为它没有编译,因此我无法在我的机器上运行它,但仍然存在一些大问题:

  • 您应该使用DateTime.Now来衡量效果。而是使用能够进行高保真度时间测量的Stopwatch,例如:
var stopwatch = Stopwatch.StartNew();
//do stuff here
stopwatch.Stop();
double timeInSeconds = stopwatch.Elapsed.TotalSeconds;
  • 您的算术在以下方面存在基本缺陷:
DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond

Ticks表示为整数(此处为long),除法结果不是实数,而是截断。例如。 55 / 7 = 7。因此,它绝对不是一种稳定的基准测试方式。

此外,使用更多元素运行基准测试,并确保在发布模式下执行此操作。

答案 1 :(得分:1)

根据您的代码,性能降低的原因不是迭代,而是来自向List<T>添加元素的操作。

这个post在比较List和LinkedList方面做得非常好。 List<T>基于数组,它分配在一个连续的块中,因此当您向其中添加更多元素时,数组将被调整大小,这会导致代码性能降低。

如果您来自C ++世界,则C#中的List<T>相当于STD中的vector<T>,而LinkedList<T>相当于STD中的list<T>