Why must a ring buffer size be a power of 2?
-
What makes you so sure it has to be a power of two? – Rob Kennedy May 10 '12 at 04:57
-
If the size of the buffer array is a power of two, the ring buffer will use more efficient masking instead of expensive modulo operations to maintain itself. – wenjianhn Mar 11 '19 at 03:23
-
The OP should have explained why he thinks (who said that?) the size must be a power of 2, and he should mark a valid answer. Still I think the question (if justified at all) can trivially be answered with "because `x mod 2^n` can be implemented as `x & (2^n - 1)`, assuming an implementation where the items are stored in an array indexed from 0 to 2^n - 1. However with modern CPUs and compilers that shouldn't actually make a big difference. – U. Windl Nov 03 '20 at 11:03
1 Answers
It must be a power of 2 to use the approach detailed below. It need not be otherwise.
A common approach looks like "if (index >= size) { index = size - index; }" (size of 10, index 10, resulting index is 0). This is slower and prone to error relative to the following approach.
Using a power of two allows us to take advantage of the following:
size = 32
bin(size) => '00100000'
mask = size - 1;
bin(mask) => '00011111'
Applying this mask with a bitwise and, we can isolate only the bits that comprise numbers in the range of 0 - 31 as the index grows:
index = 4
bin(4 & mask) => '00000100' (4)
# index 32 wraps. note here that we do no bounds checking,
# no manipulation of the index is necessary. we can simply
# and safely use the result.
index = 32
bin(index & mask) => '00000000' (0)
index = 33
bin(index & mask) => '00000001' (1)
index = 64
bin(index & mask) => '00000000' (0)
index = 65
bin(index & mask) => '00000001' (1)
This approach requires no comparisons, no branches, and is safe (resulting index always within bounds). It has the added benefit of not trashing information; while index 65 addresses element 1, I still retain the information that the index is logically 65 (which proves quite useful).
I'd also like to add that this is just as efficient when the index grows to 3456237 (address 13 in the buffer) as when it's 3.
I know I'm late to the party, I'm not even sure how I found this question :-) Hope this helps.

- 716
- 6
- 6