链表插入速度

发布于 2024-12-11 07:29:26 字数 1120 浏览 1 评论 0原文

在性能测试时,我注意到一些有趣的事情。

我注意到第一次插入 LinkedList(C# 泛型)比在列表头部完成的任何其他插入要慢得多。我只是使用了 C# 模板 LinkedList,并使用 AddFirst() 来每次插入 LinkedList。为什么第一次插入最慢?


前五个插入结果:

第一次插入列表:0.0152毫秒

第二次插入列表(在头部):0.0006毫秒

第三次插入列表(在头部):0.0003毫秒

第四次插入插入列表(在头部):0.0006 毫秒

第五次插入列表(在头部):0.0006 毫秒

性能测试代码:

        using (StreamReader readText = new StreamReader("MillionNumbers.txt"))
        {
            String line;
            Int32 counter = 0; 
            while ((line = readText.ReadLine()) != null)
            {

                watchTime.Start();
                theList.AddFirst(line);
                watchTime.Stop();
                Double time = watchTime.Elapsed.TotalMilliseconds;
                totalTime = totalTime + time; 
                Console.WriteLine(time);
                watchTime.Reset();
                ++counter; 
            }
            Console.WriteLine(totalTime);
            Console.WriteLine(counter);
            Console.WriteLine(totalTime / counter); 
        }

While performance testing, I noticed something interesting.

I noticed that the very first insertion into a LinkedList(C# Generics) is extremely slower than any other insertion done at the head of the list. I simply used the C# template LinkedList and used AddFirst() for each insertion into the LinkedList. Why is the very first insertion the slowest?


First Five Insertion Results:

First insertion into list: 0.0152 milliseconds

Second insertion into list(at head): 0.0006 milliseconds

Third insertion into list(at head): 0.0003 milliseconds

Fourth insertion into list(at head): 0.0006 milliseconds

Fifth insertion into list(at head): 0.0006 milliseconds

Performance Testing Code:

        using (StreamReader readText = new StreamReader("MillionNumbers.txt"))
        {
            String line;
            Int32 counter = 0; 
            while ((line = readText.ReadLine()) != null)
            {

                watchTime.Start();
                theList.AddFirst(line);
                watchTime.Stop();
                Double time = watchTime.Elapsed.TotalMilliseconds;
                totalTime = totalTime + time; 
                Console.WriteLine(time);
                watchTime.Reset();
                ++counter; 
            }
            Console.WriteLine(totalTime);
            Console.WriteLine(counter);
            Console.WriteLine(totalTime / counter); 
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情场扛把子 2024-12-18 07:29:27

为单个操作计时是非常危险的——最轻微的卡顿都会对结果产生巨大的影响。此外,不清楚在此代码之前您是否已使用 LinkedList 完成任何操作,这意味着您需要对 AddFirst 甚至可能涉及整个其他类型。

仅对第一次插入进行计时相当困难,因为一旦完成,就无法轻易重复。但是,您可以重复“插入和删除”的时间,就像这段代码所做的那样:

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Program
{
    public static void Main(string[] args)
    {
        // Make sure we've JITted the LinkedList code
        new LinkedList<string>().AddFirst("ignored");

        LinkedList<string> list = new LinkedList<string>();        
        TimeInsert(list);
        list.AddFirst("x");
        TimeInsert(list);
        list.AddFirst("x");
        TimeInsert(list);
        list.AddFirst("x");        
    }

    const int Iterations = 100000000;

    static void TimeInsert(LinkedList<string> list)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            list.AddFirst("item");
            list.RemoveFirst();
        }
        sw.Stop();

        Console.WriteLine("Initial size: {0}; Ticks: {1}",
                           list.Count, sw.ElapsedTicks);
    }
}

我的结果:

Initial size: 0; Ticks: 5589583
Initial size: 1; Ticks: 8137963
Initial size: 2; Ticks: 8399579

这是我所期望的,因为根据内部表示,在连接“前一个头”方面还需要做更多的工作" 在添加和删除已填充的列表时。

我的猜测是您看到的是 JIT 时间,但实际上您的代码的时间不够准确,无法发挥作用,IMO。

Timing a single operation is very dangerous - the slightest stutter can make a huge difference in results. Additionally, it's not clear that you've done anything with LinkedList<T> before this code, which means you'd be timing the JITting of AddFirst and possibly even whole other types involved.

Timing just the first insert is rather difficult as once you've done it, you can't easily repeat it. However, you can time "insert and remove" repeatedly, as this code does:

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Program
{
    public static void Main(string[] args)
    {
        // Make sure we've JITted the LinkedList code
        new LinkedList<string>().AddFirst("ignored");

        LinkedList<string> list = new LinkedList<string>();        
        TimeInsert(list);
        list.AddFirst("x");
        TimeInsert(list);
        list.AddFirst("x");
        TimeInsert(list);
        list.AddFirst("x");        
    }

    const int Iterations = 100000000;

    static void TimeInsert(LinkedList<string> list)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < Iterations; i++)
        {
            list.AddFirst("item");
            list.RemoveFirst();
        }
        sw.Stop();

        Console.WriteLine("Initial size: {0}; Ticks: {1}",
                           list.Count, sw.ElapsedTicks);
    }
}

My results:

Initial size: 0; Ticks: 5589583
Initial size: 1; Ticks: 8137963
Initial size: 2; Ticks: 8399579

This is what I'd expect, as depending on the internal representation there's very slightly more work to do in terms of hooking up the "previous head" when adding and removing to an already-populated list.

My guess is you're seeing JIT time, but really your code doesn't really time accurately enough to be useful, IMO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文