一个被BCL遗忘的高性能集合:C# CircularBuffer<T>深度解析
一个被BCL遗忘的高性能集合C# CircularBuffer深度解析在 .NET 的 BCLBase Class Library中我们习惯了ListT、DictionaryTKey, TValue、QueueT这些常用集合。但有一个高性能数据结构——环形缓冲区Circular Buffer它既不在System.Collections.Generic命名空间下也没有被官方文档重点提及却在高性能日志、网络传输、实时数据流处理中扮演着关键角色。本文将带你从零开始深度解析如何在 C# 中实现并应用一个高效的CircularBufferT。—## 1. 为什么需要环形缓冲区想象一个场景你正在处理网络数据包数据到达速率不稳定有时每秒上千条有时几秒才来一条。如果使用ListT存储所有数据内存会无限增长如果使用QueueT但只保留最近 N 条则需要频繁出队和入队且QueueT内部数组扩容时会有性能开销和内存碎片。环形缓冲区的核心思想是复用固定大小的内存块通过头尾指针实现“覆盖旧数据”的逻辑。它适用于- 实时数据流如传感器数据、股票行情- 日志滚动写入只保留最近 1000 条日志- 生产者/消费者模式下的有界队列—## 2. 基础概念从数组到环形我们从一个简单数组开始csharp// 基础数组长度固定但无法循环利用空间int[] buffer new int[5];环形缓冲区的核心是两个索引-_head指向下一个要写入的位置-_tail指向下一个要读取的位置当_head到达数组末尾时它回绕到开头通过取模运算从而形成“环”。下面是一个最小实现csharppublic class SimpleCircularBufferT{ private readonly T[] _buffer; private int _head; // 写指针 private int _tail; // 读指针 private int _count; // 当前元素数量 public SimpleCircularBuffer(int capacity) { _buffer new T[capacity]; _head 0; _tail 0; _count 0; } public void Enqueue(T item) { if (_count _buffer.Length) throw new InvalidOperationException(Buffer is full); _buffer[_head] item; _head (_head 1) % _buffer.Length; _count; } public T Dequeue() { if (_count 0) throw new InvalidOperationException(Buffer is empty); T item _buffer[_tail]; _tail (_tail 1) % _buffer.Length; _count--; return item; }}这个版本已能工作但有几个问题1. 满了之后无法覆盖旧数据抛异常2. 没有线程安全3. 性能上每次取模有硬件开销但现代 CPU 可优化—## 3. 进阶支持覆盖的循环缓冲区在日志场景中我们通常希望缓冲区满时自动覆盖最旧的数据。修改Enqueue逻辑csharppublic class OverwriteCircularBufferT{ private readonly T[] _buffer; private int _head; private int _tail; private int _count; public OverwriteCircularBuffer(int capacity) { _buffer new T[capacity]; } public void Enqueue(T item) { _buffer[_head] item; _head (_head 1) % _buffer.Length; if (_count _buffer.Length) _tail (_tail 1) % _buffer.Length; // 覆盖时移动读指针 else _count; } public T Dequeue() { if (_count 0) throw new InvalidOperationException(Empty); T item _buffer[_tail]; _tail (_tail 1) % _buffer.Length; _count--; return item; } public int Count _count; public int Capacity _buffer.Length;}这里的关键是当缓冲区已满时写入新数据会导致_tail也向前移动从而丢弃最旧的数据。这种设计非常适合“只保留最近 N 条”的场景。—## 4. 高级优化避免取模运算虽然取模运算在 .NET 中经过优化但在高频写入如每秒百万次时仍可能成为瓶颈。一种经典优化是让容量为 2 的幂然后用位运算替代取模csharppublic class FastCircularBufferT{ private readonly T[] _buffer; private int _head; private int _tail; private int _count; private readonly int _mask; // 容量-1 public FastCircularBuffer(int capacity) { // 将容量向上取整为2的幂 capacity (int)Math.Pow(2, Math.Ceiling(Math.Log(capacity, 2))); _buffer new T[capacity]; _mask capacity - 1; } public void Enqueue(T item) { _buffer[_head] item; _head (_head 1) _mask; // 位运算代替取模 if (_count _buffer.Length) _tail (_tail 1) _mask; else _count; } public T Dequeue() { if (_count 0) throw new InvalidOperationException(Empty); T item _buffer[_tail]; _tail (_tail 1) _mask; _count--; return item; }}注意 _mask等价于% _buffer.Length但速度更快。此优化在 .NET 7 中尤其明显因为 JIT 会自动识别某些模式。—## 5. 完整示例实时数据缓存下面是一个完整的可运行示例演示如何使用环形缓冲区缓存股票价格并显示最近 10 条数据csharpusing System;using System.Threading;class Program{ static void Main() { // 创建一个容量为5的环形缓冲区 var buffer new OverwriteCircularBufferdouble(5); // 模拟产生数据 Random rand new Random(); for (int i 0; i 10; i) { double price 100 rand.NextDouble() * 10; buffer.Enqueue(price); Console.WriteLine($写入: {price:F2} | 当前数量: {buffer.Count}); Thread.Sleep(100); } Console.WriteLine(\n--- 读取所有数据应只有最近5条 ---); while (buffer.Count 0) { Console.WriteLine($读取: {buffer.Dequeue():F2}); } }}// 复用上面的 OverwriteCircularBufferT 类public class OverwriteCircularBufferT{ private readonly T[] _buffer; private int _head; private int _tail; private int _count; public OverwriteCircularBuffer(int capacity) { _buffer new T[capacity]; } public void Enqueue(T item) { _buffer[_head] item; _head (_head 1) % _buffer.Length; if (_count _buffer.Length) _tail (_tail 1) % _buffer.Length; else _count; } public T Dequeue() { if (_count 0) throw new InvalidOperationException(Empty); T item _buffer[_tail]; _tail (_tail 1) % _buffer.Length; _count--; return item; } public int Count _count; public int Capacity _buffer.Length;}运行结果示例写入: 105.32 | 当前数量: 1写入: 103.87 | 当前数量: 2...写入: 108.11 | 当前数量: 5写入: 107.55 | 当前数量: 5 // 开始覆盖...--- 读取所有数据应只有最近5条 ---读取: 106.44读取: 104.29读取: 108.11读取: 107.55读取: 102.93—## 6. 线程安全与性能考量BCL 中的System.Collections.Concurrent提供了ConcurrentQueueT但它是无界或有界的有界版本需要 .NET 8 的BoundedChannel。环形缓冲区在单生产者单消费者场景下可以做到无锁csharppublic class LockFreeCircularBufferT{ private readonly T[] _buffer; private int _head; private int _tail; private int _count; private readonly int _mask; public LockFreeCircularBuffer(int capacity) { capacity (int)Math.Pow(2, Math.Ceiling(Math.Log(capacity, 2))); _buffer new T[capacity]; _mask capacity - 1; } // 要求单生产者调用 public void Enqueue(T item) { // 假设有空间否则覆盖 _buffer[_head] item; _head (_head 1) _mask; Interlocked.Increment(ref _count); // 原子更新 } // 要求单消费者调用 public bool TryDequeue(out T result) { if (Volatile.Read(ref _count) 0) { result default; return false; } result _buffer[_tail]; _tail (_tail 1) _mask; Interlocked.Decrement(ref _count); return true; }}注意Interlocked操作有一定开销但比锁lock快得多。在极高性能需求下可以使用System.Threading.SpinLock或内存屏障。—## 7. 总结环形缓冲区是 BCL 中“隐藏的宝石”——虽然官方没有提供通用实现但它在功能上与QueueT互补在性能上优于ListT的频繁插入删除。本文从基础数组环开始逐步优化到支持覆盖、位运算加速、无锁并发展示了其在不同场景下的应用价值。核心要点回顾1.固定内存避免频繁扩容和 GC 压力2.覆盖机制适合“只保留最近 N 条”的数据流3.性能优化容量设为 2 的幂用代替%4.并发支持单生产者单消费者场景可无锁如果你在开发实时系统、日志库或游戏服务器中的消息队列不妨抛弃ListT自己实现一个CircularBufferT——它可能成为你工具箱中最锋利的刀。BCL 没有提供不代表它不重要而是给了你自由定制的机会。

相关新闻

7-Zip-zstd:免费增强版压缩工具,让文件压缩效率提升300%

7-Zip-zstd:免费增强版压缩工具,让文件压缩效率提升300%

7-Zip-zstd:免费增强版压缩工具,让文件压缩效率提升300% 【免费下载链接】7-Zip-zstd 7-Zip with support for Brotli, Fast-LZMA2, Lizard, LZ4, LZ5 and Zstandard 项目地址: https://gitcode.com/gh_mirrors/7z/7-Zip-zstd 你是否还在使用传统…

2026/8/1 13:01:36 阅读更多 →
WebPShop:Photoshop终极WebP格式插件解决方案

WebPShop:Photoshop终极WebP格式插件解决方案

WebPShop:Photoshop终极WebP格式插件解决方案 【免费下载链接】WebPShop Photoshop plug-in for opening and saving WebP images 项目地址: https://gitcode.com/gh_mirrors/we/WebPShop 还在为Photoshop的WebP支持功能不完整而烦恼吗?WebPShop插…

2026/8/1 13:01:36 阅读更多 →
Ohook:终极免费Office激活方案,3分钟永久解锁Microsoft 365完整功能

Ohook:终极免费Office激活方案,3分钟永久解锁Microsoft 365完整功能

Ohook:终极免费Office激活方案,3分钟永久解锁Microsoft 365完整功能 【免费下载链接】ohook An universal Office "activation" hook with main focus of enabling full functionality of subscription editions 项目地址: https://gitcode.…

2026/8/1 13:00:35 阅读更多 →

最新新闻

Slidev终极指南:让技术演示告别枯燥的开发者利器

Slidev终极指南:让技术演示告别枯燥的开发者利器

Slidev终极指南:让技术演示告别枯燥的开发者利器 【免费下载链接】slidev Presentation Slides for Developers 项目地址: https://gitcode.com/GitHub_Trending/sl/slidev 还在为技术演示而烦恼吗?每次分享代码时,要么在PPT中截图导致…

2026/8/1 13:59:55 阅读更多 →
从零部署语音控制机械臂:基于ReSpeaker与HorizonArm-Mark的具身智能实践

从零部署语音控制机械臂:基于ReSpeaker与HorizonArm-Mark的具身智能实践

1. 项目缘起:当机械臂“听懂”人话,会发生什么?几年前,我第一次尝试给一台六轴机械臂编程,让它完成一个简单的“抓取-放置”动作。那是一个漫长的下午,我对着示教器,一遍遍地调整关节角度、设置…

2026/8/1 13:59:55 阅读更多 →
3步搞定HTML转Word:这个开源神器让文档转换零门槛

3步搞定HTML转Word:这个开源神器让文档转换零门槛

3步搞定HTML转Word:这个开源神器让文档转换零门槛 【免费下载链接】html-to-docx HTML to DOCX converter 项目地址: https://gitcode.com/gh_mirrors/ht/html-to-docx 你是否曾为网页内容无法完美保存为Word文档而烦恼?复制粘贴导致格式混乱&…

2026/8/1 13:59:55 阅读更多 →
AI模型训练日志失控真相(Log4j2 + LLM Pipeline 日志泄露事故复盘)

AI模型训练日志失控真相(Log4j2 + LLM Pipeline 日志泄露事故复盘)

更多请点击: https://kaifayun.com 第一章:AI模型训练日志失控真相(Log4j2 LLM Pipeline 日志泄露事故复盘) 某头部AI平台在LLM微调 pipeline 中突发敏感信息泄露事件,根源直指 Log4j2 在异步日志场景下的 JNDI 表达…

2026/8/1 13:59:55 阅读更多 →
现在不重构CI,3个月后将被迫重写全部Pipeline:AI编程驱动下的CI架构迁移倒计时

现在不重构CI,3个月后将被迫重写全部Pipeline:AI编程驱动下的CI架构迁移倒计时

更多请点击: https://codechina.net 第一章:AI编程驱动下的CI架构迁移倒计时 持续集成(CI)正站在一场范式转移的临界点——AI编程工具不再仅是开发者助手,而是逐步成为CI流水线的“协同编排者”与“自主决策节点”。传…

2026/8/1 13:59:55 阅读更多 →
【AI版本兼容性检测黄金法则】:20年架构师亲授5大避坑指南,90%团队都忽略了第3步?

【AI版本兼容性检测黄金法则】:20年架构师亲授5大避坑指南,90%团队都忽略了第3步?

更多请点击: https://codechina.net 第一章:AI版本兼容性检测的底层逻辑与核心挑战 AI版本兼容性检测并非简单的API签名比对,而是横跨模型架构、算子语义、运行时依赖与量化规范的多维一致性验证。其底层逻辑建立在三个锚点之上&#xff1a…

2026/8/1 13:58:55 阅读更多 →

日新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/8/1 13:02:46 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/8/1 5:19:34 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/8/1 10:33:33 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/1 0:00:48 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/1 0:00:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/1 0:00:48 阅读更多 →