Circular Buffer / Ring Buffer
Also Known As
ring buffer
circular queue
FIFO buffer
TL;DR
A fixed-size array treated as circular — the write pointer wraps around when it reaches the end, overwriting the oldest data. Used for logs, audio streaming, and producer-consumer queues.
Explanation
A circular buffer has a head (read) and tail (write) pointer. Write: place at tail, advance tail % capacity. Read: take from head, advance head % capacity. Full: tail + 1 == head. Empty: head == tail. O(1) read and write. Fixed memory — no allocation after creation. Overwrite mode: when full, advance head (discard oldest) without blocking. Lock-free single-producer/single-consumer implementations exist using atomic operations. Used in: kernel ring buffers, audio/video streaming, network packet queues, and rolling log windows.
Common Misconception
✗ A circular buffer is just a queue — a standard queue grows unboundedly; a circular buffer has fixed memory and either blocks or overwrites on overflow — the fixed memory is the defining property.
Why It Matters
A logging system that uses a circular buffer keeps the last N log lines in memory with O(1) write — no allocation, no GC pressure, and a fixed memory footprint regardless of how many events are logged.
Common Mistakes
- Not handling the full condition — writing to a full buffer silently overwrites unread data.
- Using modulo on non-power-of-2 sizes in tight loops — use bitwise AND with power-of-2 size for speed.
- Not making the buffer size a power of 2 — % operation can be replaced with & (size-1).
- Shared circular buffer without synchronisation — concurrent read/write requires locks or atomic operations.
Code Examples
✗ Vulnerable
// Dynamic array as log buffer — unbounded memory:
$logs = [];
while (true) {
$logs[] = readEvent(); // Grows forever — OOM after enough events
}
✓ Fixed
// Circular buffer — fixed memory, O(1) operations:
class CircularBuffer {
private array $buffer;
private int $head = 0;
private int $tail = 0;
private int $size = 0;
public function __construct(private int $capacity) {
$this->buffer = array_fill(0, $capacity, null);
}
public function write(mixed $item): void {
$this->buffer[$this->tail] = $item;
$this->tail = ($this->tail + 1) % $this->capacity;
if ($this->size < $this->capacity) $this->size++;
else $this->head = ($this->head + 1) % $this->capacity; // Overwrite oldest
}
public function read(): mixed {
if ($this->size === 0) return null;
$item = $this->buffer[$this->head];
$this->head = ($this->head + 1) % $this->capacity;
$this->size--;
return $item;
}
}
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
16 Mar 2026
Edited
22 Mar 2026
Views
18
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 7
Perplexity 3
Ahrefs 2
Unknown AI 2
Also referenced
How they use it
crawler 14
Related categories
⚡
DEV INTEL
Tools & Severity
🟢 Low
⚙ Fix effort: Medium
⚡ Quick Fix
Use a circular buffer (ring buffer) when you need a fixed-size queue where old data is overwritten — PHP's SplFixedArray or a simple array with modulo indexing
📦 Applies To
PHP 5.0+
web
cli
🔗 Prerequisites
🔍 Detection Hints
array_shift() on large arrays to maintain fixed-size queue (O(n) reindex); storing N most recent items by slicing growing array
Auto-detectable:
✗ No
blackfire
⚠ Related Problems
🤖 AI Agent
Confidence: Low
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: Class
Tests: Update