Why is a LinkedList Generally Slower than a List?

前端 未结 6 535
旧时难觅i
旧时难觅i 2021-02-01 13:47

I started using some LinkedList’s instead of Lists in some of my C# algorithms hoping to speed them up. However, I noticed that they just felt slower. Like any good developer, I

6条回答
  •  青春惊慌失措
    2021-02-01 14:32

    I highly recommend the article Number crunching: why you should never use a linked-list again. There isn't much there that isn't anywhere else, but I spent quite a bit of time trying to figure out why LinkedList was so much slower than List in situations I thought would obviously favor the linked list before I found it, and after looking it over, things made a bit more sense:

    The linked list has items in disjoint areas of memory, and as a result, one could say it is cache line hostile, because it maximizes cache misses. The disjoint memory makes traversing the list result in frequent and costly unexpected RAM lookups.

    A vector [equivalent to ArrayList or List] on other hand has its items stored in adjacent memory, and in so doing, is able to maximize cache utilization and avoid cache misses. Often, in practice, this more than offsets the cost incurred when shuffling data around.

    If you'd like to hear that from a more authoritative source, this is from Tips for Improving Time-Critical Code on MSDN:

    Sometimes a data structure that looks great turns out to be horrible because of poor locality of reference. Here are two examples:

    • Dynamically allocated linked lists (LinkedListNode is a reference type, so it is dynamically allocated) can reduce program performance because when you search for an item or when you traverse a list to the end, each skipped link could miss the cache or cause a page fault. A list implementation based on simple arrays might actually be much faster because of better caching and fewer page faults— even allowing for the fact that the array would be harder to grow, it still might be faster.

    • Hash tables that use dynamically allocated linked lists can degrade performance. By extension, hash tables that use dynamically allocated linked lists to store their contents might perform substantially worse. In fact, in the final analysis, a simple linear search through an array might actually be faster (depending on the circumstances). Array-based hash tables (IIRC, Dictionary is array-based) are an often-overlooked implementation which frequently has superior performance.


    This is my original (far less useful) answer where I did some performance tests.

    The general consensus seems to be that the linked list is allocating memory on every add (because the node is a class) and that does seem to be the case. I tried to isolate the allocation code from the timed code that adds items to the list and made a gist from the result: https://gist.github.com/zeldafreak/d11ae7781f5d43206f65

    I run the test code 5 times and call GC.Collect() between them. Inserting 20 million nodes into the linked list takes 193-211ms (198ms) compared to 77-89ms (81ms), so even without the allocation, a standard list is a little over 2x faster. Iterating over a list takes 54-59ms, compared to 76-101ms for the linked list, which is a more modest 50%-ish faster.

提交回复
热议问题