You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何LinkedList与List操作基准测试结果存在异常?

LinkedList与List插入操作基准测试异常分析

问题情况

我在对LinkedList和List的插入操作做基准测试,理论上LinkedList的插入操作都是O(1)时间复杂度,但测试中出现了两个不符合预期的异常:

  • 样本量为100时,LinkedList的中间插入操作耗时出现明显峰值(3854 ticks)
  • 样本量为100000时,List的前置插入操作耗时大幅飙升(272081 ticks)
    多次运行测试都出现同样情况,就算为每个操作、每个样本量单独创建Stopwatch,结果还是不符合预期的时间复杂度规律。

测试代码

void ListInsertionComparison()
{
    for (var i = 100; i <= 1000000; i*=10)
    {
        var stopwatch = new Stopwatch();

        var random = new Random(12345);
        var localList = new List<int>();
        var localLinkedList = new LinkedList<int>();
        var middleNode = new LinkedListNode<int>(5);

        for (var j = 0; j < i; j++)
        {
            localList.Add(j);
            var temp = localLinkedList.AddLast(j);
            if (j == i / 2)
                middleNode = temp;
        }

        stopwatch.Reset();
        stopwatch.Start();
        localList.Insert(0,1);
        stopwatch.Stop();
        Console.WriteLine($"List Prepend: {i} {stopwatch.ElapsedTicks}");

        stopwatch.Reset();
        stopwatch.Start();
        localLinkedList.AddFirst(1);
        stopwatch.Stop();
        Console.WriteLine($"LinkedList Prepend: {i} {stopwatch.ElapsedTicks}");

        stopwatch.Reset();
        stopwatch.Start();
        localList.Insert(localList.Count/2, 1);
        stopwatch.Stop();
        Console.WriteLine($"List Insert: {i} {stopwatch.ElapsedTicks}");

        stopwatch.Reset();
        stopwatch.Start();
        localLinkedList.AddBefore(middleNode, 1);
        stopwatch.Stop();
        Console.WriteLine($"LinkedList Insert: {i} {stopwatch.ElapsedTicks}");
    }
}

测试输出结果

List Prepend: 100 160
LinkedList Prepend: 100 16
List Insert: 100 24
LinkedList Insert: 100 3854
List Prepend: 1000 7
LinkedList Prepend: 1000 2
List Insert: 1000 7
LinkedList Insert: 1000 11
List Prepend: 10000 12
LinkedList Prepend: 10000 2
List Insert: 10000 10
LinkedList Insert: 10000 2
List Prepend: 100000 272081
LinkedList Prepend: 100000 4
List Insert: 100000 575
LinkedList Insert: 100000 57
List Prepend: 1000000 8929
LinkedList Prepend: 1000000 6
List Insert: 1000000 3652
LinkedList Insert: 1000000 15

异常原因分析

1. LinkedList样本量100时的插入峰值

这是首次JIT编译导致的。第一次执行AddBefore方法时,.NET运行时需要把该方法的IL代码编译成机器码,这个编译过程的额外耗时被计入了首次测试的tick数。后续测试时方法已经完成编译,耗时就回归到正常的O(1)水平了。

2. List样本量100000时的前置插入峰值

List底层是数组,前置插入需要把所有元素向后移动一位,时间复杂度是O(n)。这个量级下的峰值主要是:

  • 移动100000个元素的操作本身就会产生可观耗时,只是小样本量时不明显;
  • 可能叠加了内存页缓存未命中的情况,或者刚好触发了垃圾回收,进一步拉高了耗时。

测试优化建议

  • 预热代码:正式测试前先完整跑一遍所有操作,触发JIT编译,避免首次编译的干扰;
  • 多次取平均:每个操作重复执行几十上百次,取平均耗时,减少单次测试的偶然波动;
  • 隔离测试:把前置插入、中间插入等操作分开测试,避免不同操作之间的状态影响。

内容的提问来源于stack exchange,提问作者Daar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:15:50