und die alten Daten bleiben einfach unangetastet im Ring
Das geht auch nur solange gut, bis der generische Ringbuffer mit Managed Types verwendet wird. Dann muss beim Entfernen eventuell schon was mit den alten Daten passieren (z.B. Interfaces auf nil setzen). Das bedeutet manchmal eben auch Schreibzugriffe auf den Bufferspeicher zusätzlich zu den Pointern mit allem was es bei Multithreading dabei zu beachten gibt. Generics sind halt nicht trivial und verursachen oft einen ziemlichen Overhead, der bei simplen Typen zwar redundant ist, aber nicht immer so leicht wegoptimiert werden kann.