2010-03-31 111 views

回答

26

我已经用它来限制大小的内存日志。例如,应用程序会在处理用户请求时写入日志条目。无论何时发生异常(这会对处理造成干扰),当前在内存中的日志记录将与其一起转储。

循环缓冲区的好处是,您不需要无限量的内存,因为旧的条目会自动覆盖。 “challange”是,你需要为你的用例找到合适的尺寸。在上面的例子中,当具有关于异常的最重要信息的日志记录已被覆盖时,将是非常不幸的。

某些系统/应用程序有工具可让您按需提取缓冲区的当前内容,而不仅仅是在自动提取缓冲区时(如果曾经)。

我相信ETW和CLRs stress log,以及许多其他系统的内核或高性能跟踪/日志,都是这样实现的。

使用这样的缓冲区进行内存中的跟踪/日志记录的概念实际上很常见(并不是说这是唯一的用途 - 当然不是),因为它比写入记录到文件/数据库要快除非发生错误,否则您可能永远不会感兴趣。在相关说明中,它节省了硬盘空间。

+8

+1“I've用它来代替......“而不是”你可以用它来......“ – ryeguy 2010-03-31 14:56:47

6

我知道这是作弊,但维基百科确实有很好的解释。

http://en.wikipedia.org/wiki/Circular_buffer

循环缓冲器,环状缓冲器或 环形缓冲器是 使用一个单一的,固定大小的缓冲器,就好像它 已连接的端至端的数据结构。此 结构使它容易地以 缓冲数据流

可能可能使用一个 覆盖循环缓冲器是 多媒体一个例子。如果缓冲区被用作 在 生产者 - 消费者问题的界缓冲区那么 可能期望生产者 (例如,音频发生器),以 覆盖旧数据如果消费者 (如声卡)无法 随时跟上。另一个例子 是数字波导合成方法 使用循环缓冲器来有效地模拟振动弦或管乐器的声音。

关于与双链表比较,我想它确实取决于你使用的列表...实现环形缓冲区似乎更复杂,请(再次)参考wiki页;这解释了实现,注意事项等,并且还显示了示例代码。

谢谢,尼尔

+0

我的第一个SO问题的答案对音频发生器使用循环缓冲区http://stackoverflow.com/questions/664594/how-to-generate-a-guitar-note – 2010-03-31 14:47:39

5

循环缓冲区是一种很好的机制,可以按顺序方式有效地维护滑动/移动值/项目列表。一个例子可能是保持最后N个项目的滑动平均值。假设您想跟踪计算某个值的最后100次操作的平均成本。要做到这一点,您需要删除最旧的费用并添加最新的费用。

没有一个循环缓冲区,这样做的代价很高的机制(C风格)就是拥有一个100个元素的数组。每次计算新的成本时,您可以将99个元素缩小并将新元素放在最后位置。这显然是昂贵的。使用循环缓冲的想法,你只需要追踪缓冲区的“结束”(位置0-99)。它将标记最老的(或最新的...无论您选择哪个)成本项目的位置。在读取旧值(用于更新运行平均值)之后,将其替换为最新值并递增缓冲区位置(如果它为99,则将其设置回0 ...因此为圆形部分)。

将它与双向链表进行比较并不合理。循环缓冲区当然可以用双向链表(甚至单个链表)来实现。但比较它们有点像比较苹果和橙子可以这么说。

0

我用它作为实现循环调度的简单方法。基本上我有一堆不同的对象,可以产生消费者可以处理的价值。我把所有的制作人都放在一个圈子里,然后依次询问每一个。

0

我在多线程代码中使用了环形缓冲区。基本上,如果所有插槽都满了,制作人必须等待。消费者只需处理“满”的插槽中的项目。

这是我开始的一个线程。它对实施有一些很好的建议。

.NET multi-threaded variable access

11

循环缓冲器有利于在嵌入式系统的串行数据流。微控制器通常有一个UART来处理进入的串行字节,这些需要按顺序存储并稍后处理(字节通常以比它们能够处理的速度更快的速率进入)。

缓冲区有效地将所需的时序关键响应(当字节进入时,以微秒为单位)分割为对整个消息的非时序关键响应(例如显示进入的信息,以毫秒为单位),例如:

1)接收到一个字节后,UART可以产生一个中断,软件通过快速接收到的字节并将其推送到缓冲区的末尾来响应该中断。

2)后台软件例程可以定期检查缓冲区中是否有任何东西,并根据需要将其清空。

由于循环缓冲区大小可以定义为预编译,因此大小是有限的。这有助于提高空间利用率,并且应该消除内存损坏,以消除数据开始丢失之前可以接收的字节数。