Skip to main content

Ring Buffer

A ring buffer is a data structure that efficiently manages a fixed-size, cyclically-referenced buffer, allowing for constant-time insertions and removals while overwriting the oldest data when full.

Advantages

  • Constant Time Complexity for Insertions and Deletions: Ring buffers offer O(1) time complexity for both inserting elements (enqueue) and removing elements (dequeue) as long as the buffer is not full or empty. This makes them highly efficient for real-time applications where performance matters.
  • Fixed and Predictable Memory Usage: Ring buffers have a fixed capacity, which means that memory usage is predictable and doesn't grow beyond the specified limit. This characteristic is crucial in embedded systems and other resource-constrained environments.
  • Efficient for Streaming and Circular Data: Ring buffers are ideal for managing streaming data, such as audio, video, or sensor data, as they provide a continuous loop for storing and processing the most recent data points.
  • No Need for Dynamic Memory Allocation: Unlike dynamic data structures like linked lists or arrays with variable sizes, ring buffers do not require dynamic memory allocation or deallocation. This eliminates potential memory fragmentation issues and improves memory management efficiency.

Disadvantages

  • Fixed Capacity Limitation: The fixed size of a ring buffer can be a disadvantage if the number of elements you need to store exceeds the buffer's capacity. In such cases, you would need to implement additional logic for handling overflow conditions.
  • Inefficient for Non-Circular Data: Ring buffers are designed for circular data usage, so they are not suitable for scenarios where you need to retain all historical data without overwriting any of it.
  • Insertions May Overwrite Data: When the buffer is full and new elements are inserted, they overwrite the oldest elements. This behavior may not be suitable for all applications, especially if you need to preserve a complete history of data.

Code

using Extended.Collections.Generic;

public class RingBufferSandbox : Sandbox
{
private readonly RingBuffer<string> m_buffer = new (3);

protected override void Run()
{
m_buffer.Add("A");
m_buffer.Add("B");
m_buffer.Add("C");
Logger.Information("1. {Buffer}", m_buffer); // 1. [ "A", "B", "C" ]

m_buffer.Add("D");
Logger.Information("2. {Buffer}", m_buffer); // 2. [ "B", "C", "D" ]

m_buffer.Remove("C");
Logger.Information("3. {Buffer}", m_buffer); // 3. [ "B", "D" ]

m_buffer.Add("E");
Logger.Information("4. {Buffer}", m_buffer); // 4. [ "B", "D", "E" ]

m_buffer.Clear();
Logger.Information("5. {Buffer}", m_buffer); // [ ]
}
}