Что такое кольцевой буфер и где он применяется?
Массивы и списки
Кольцевой буфер — массив фиксированного размера с индексами чтения и записи, которые при достижении конца переходят в начало; он даёт очередь FIFO с O(1) на операцию и без аллокаций после создания.
Устройство
class RingBuffer {
#buf;
#head = 0; // откуда читать
#size = 0;
constructor(cap) { this.#buf = new Array(cap); }
push(x) {
if (this.#size === this.#buf.length) return false; // или перезаписать старый
this.#buf[(this.#head + this.#size) % this.#buf.length] = x;
this.#size++;
return true;
}
shift() {
if (this.#size === 0) return undefined;
const x = this.#buf[this.#head];
this.#buf[this.#head] = undefined; // не держим ссылку для GC
this.#head = (this.#head + 1) % this.#buf.length;
this.#size--;
return x;
}
}Тонкости
- «Полный» и «пустой» при голых
head === tailнеразличимы: храните счётчик или оставляйте одну ячейку пустой. - Ёмкость-степень двойки позволяет заменить
%на маску& (cap − 1). - При переполнении есть две политики: отклонять запись (очередь задач) или затирать самое старое (логи, метрики).
Где встречается
- Аудио- и видеобуферы, кольца приёма и передачи сетевых карт.
- Очереди
io_uring,kfifoв ядре Linux, LMAX Disruptor. - «Последние N событий»: скользящее окно, история команд.
Коротко для собеседования
Кольцевой буфер — очередь фиксированного размера поверх массива, где индексы заворачиваются по модулю, поэтому нет ни сдвигов, ни аллокаций. Заранее решите, что делать при переполнении — отклонять запись или затирать старое; при одном писателе и одном читателе его легко сделать lock-free.