Live data from Hacker News

Shift-to-Middle Array: A Faster Alternative to Std:Deque?

github.com

11–20 of 121 posts

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#11
A couple notes looking at the c++ implementation

- this is going to have problems with non-trivial types. (Think about destructors or move constructors like std::unique_ptr). If you don't want to deal with them, at least add a static_assert(std::is_trivially_copyable::value == true);

- front() doesn't return a reference and it doesn't even return the front

- adding iterators (begin()/end()) will let it play nice with for( : ) loops and , etc.

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#13
post #8
post #5

Earlier quoted context omitted.

The elements are completely contiguous, which can be nice for passing off (subslices) to other APIs, maximum speed iteration, etc.

Does it have to move or resize when one of the sides reaches the end of the array? I presume that would be slower than a ring buffer that only grows when it's completely filled?

Both are O(1) datastructures, but indexing a ring buffer is slightly more costly compared to this and insertion is slightly more costly for this than a ring. Probably usually works out in favor of this design though for net performance usually?

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#14

is it just me or benchmarks report link is dead and hence there's no way to see the comparison

It’s not dead as such but it looks like OP may have left over some links they intended to add.

That one and at least one other simply links to #, which means same page no anchor. And this is commonly done as a placeholder link before you have the link in place you intended to put there.

Whereas a dead link for me would be one that leads elsewhere and results in 404 (page moved, file not yet created, etc) or an expired or not yet registered domain.

But I get what you mean, and I agree OP should update those links to point somewhere :)

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#15
AFAIK, Apple's CoreFoundation CFArray also works similarly[0]. NSMutableArray works little differently (using a circular buffer). From the always excellent Cichenowski[1].

[0] - https://github.com/opensource-apple/CF/blob/master/CFArray.c [1] - https://ciechanow.ski/exposing-nsmutablearray/

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#16
post #8

Earlier quoted context omitted.

Does it have to move or resize when one of the sides reaches the end of the array? I presume that would be slower than a ring buffer that only grows when it's completely filled?

Both are O(1) datastructures, but indexing a ring buffer is slightly more costly compared to this and insertion is slightly more costly for this than a ring. Probably usually works out in favor of this design though for net performance usually?

I'd love to see performance numbers for this, if they're available. My hunch is that indexing cost would be about the same.

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#17
post #2

I recently developed a new data structure called the Shift-To-Middle Array, designed as an alternative to std::deque, std::vector, and linked lists. My goal was to optimize insertion and deletion at both ends, while also improving cache locality and performance compared to traditional implementations. What is the Shift-To-Middle Array? Unlike std::deque, which uses a fragmented block-based structure, the Shift-To-Mid…

> Unlike std::deque, which uses a fragmented block-based structure

I always assumed deque implementations were ring buffers that double in size once full so that prepend/append operations are amortized O(1).

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#18
post #10

Interesting! This is the kind of thing I like. I'm having a hard time understanding the description. If I understand right, it's kind of like an inside-out gap buffer, or a hybrid of a gap buffer and a ring buffer? Is the free space in the array always contiguous? If not, is the non-free space? How is it different from ExpandingRingBuffer?

It starts by adding the first element to the middle of the allocation and then the head and tail grow outwards as more elements are added at either end.

Once the head reaches the front of the allocation or the tail reaches the rear of the allocation, it triggers a resize. The resize creates a new allocation with double the size and copies the original elements to the middle of this new allocation.

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#19
post #8
post #5

Earlier quoted context omitted.

The elements are completely contiguous, which can be nice for passing off (subslices) to other APIs, maximum speed iteration, etc.

Does it have to move or resize when one of the sides reaches the end of the array? I presume that would be slower than a ring buffer that only grows when it's completely filled?

>Does it have to move or resize when one of the sides reaches the end of the array?

Yes, it resizes when that happens, to double the size.

Re: Shift-to-Middle Array: A Faster Alternative to Std:Deque?

#20
post #10

Interesting! This is the kind of thing I like. I'm having a hard time understanding the description. If I understand right, it's kind of like an inside-out gap buffer, or a hybrid of a gap buffer and a ring buffer? Is the free space in the array always contiguous? If not, is the non-free space? How is it different from ExpandingRingBuffer?

It starts by adding the first element to the middle of the allocation and then the head and tail grow outwards as more elements are added at either end. Once the head reaches the front of the allocation or the tail reaches the rear of the allocation, it triggers a resize. The resize creates a new allocation with double the size and copies the original elements to the middle of this new allocation.

That can't be correct, because then just adding elements at the front and removing them at the rear while maintaining a constant queue size such as 5 elements would trigger an infinite number of resizes. Maybe it only resizes under some circumstances, otherwise copying the live elements back to the middle?

It still seems like that involves copying that a straightforward ring buffer avoids.

Post reply on HN