Skip to content

Move collections.deque to a growable ring buffer for fast random accessΒ #731

@matthiasgoergens

Description

@matthiasgoergens

At the moment, collections.deque is implemented via a linked list of 64-element arrays. That means it can quickly access elements at the beginning and end, and has only a modest amount of space overhead.

However, collections.deque also offers indexing via my_deque[index] but that takes linear time.

Inspired by Rust's VecDeque, I have prototyped a double-ended queue implemented with a growable ring buffer.

The new implementation is simpler, and I ran a few simple benchmarks. Most notable, random access is now O(1).

  • Accessing the ends (append either side, pop either side) is about as fast as before.
  • Deleting an arbitrary element in the middle, inserting an element in the middle and rotation etc are still O(n), but the constant factors are better: the main bulk of the work is essentially just memmove.

One downside: just like with lists, my prototype grows the allocated space geometrically, so the worst case append-time is linear, but it's amortised constant. (There are well-known ways to make both lists and my deque prototype have O(1) append, but if they aren't worth it for lists, they probably aren't worth it for the deque. They come with a constant factor overhead.)

The new implementation should be cache friendlier, because it's just one big array, not a linked list. But I haven't devised a benchmark to investigate the impact of that, yet.

Inserting into a ring-deque with a fixed maximum length is still O(1) worst case (not just amortised), like in the original implementation. That's what the ring-buffer buys us.

The prototype is on my github, but it's not polished and still has plenty of bugs. If there's interest, I'll publish the benchmarks and make a more polished PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions