循环缓冲区有什么用途?

发布于 2024-08-27 09:52:40 字数 60 浏览 10 评论 0原文

循环缓冲区有哪些用途?

使用循环缓冲区有什么好处?

它是双链表的替代品吗?

What are some of the uses of circular buffer?

What are the benefits of using a circular buffer?

is it an alternative to double linked list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

七婞 2024-09-03 09:52:40

我已将其用于大小有限的内存中日志。例如,应用程序会在处理用户请求时写入日志条目。每当发生异常(这会破坏处理)时,当前内存中的日志记录都会随之转储。

循环缓冲区的好处是,您不需要无限量的内存,因为较旧的条目会自动覆盖。 “挑战”是,您需要找到适合您的用例的尺寸。在上面的示例中,如果包含有关异常的最重要信息的日志记录已经被覆盖,那将是非常不幸的。

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

我相信 ETW 和 CLR 压力日志以及许多其他系统的内核或高性能跟踪/日志记录都是以这种方式实现的。

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

I've used it for an in-memory log with a restricted size. For example, the application would write log entries while processing user requests. Whenever an exception occurred (that would be disruptive to the processing) the log records currently in memory would be dumped along with it.

The benefit of a circular buffer is, that you don't need infinite amounts of memory, since older entries get overridden automatically. The "challange" is, that you need to find a suitable size for your usecase. In the example above, it would be very unfortunate when the log record with the most vital information about the exception would have already been overridden.

Some systems/applications have tools to let you extract the current content of the buffer on demand, and not only when it would be extract automatically (if ever).

I believe ETW and the CLRs stress log, amongst many other system's kernel or highperformance trace/logging, are implemented that way.

The concept of using such buffers for in-memory tracing/logging is actually pretty common (not to say that this is the only use - certainly not), because it is way faster than written records to a file/database that you might never be interested in unless an error occurs. And on a related note, it conserves harddisk space.

穿透光 2024-09-03 09:52:40

循环缓冲区非常适合嵌入式系统中的串行数据流。微控制器通常有一个 UART 来处理传入的串行字节,这些字节需要按顺序存储并稍后处理(字节传入的速度通常比处理的速度快)。

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

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

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

由于循环缓冲区大小可以在编译前定义,因此大小受到限制。这有助于提高空间效率,并且应该消除内存损坏,但要权衡在数据开始丢失之前可以接收多少字节。

Circular buffers are good for serial data streams in embedded systems. Microcontrollers often have a UART to handle a serial byte coming in, these need to be stored in order and dealt with later (bytes often come in at a faster rate than they can be handled).

The buffer effectively splits the timing-critical response required (when the bytes come in, in microseconds) to the non timing-critical response to the whole message (for example displaying the message which came in, in milliseconds), e.g.:

1) Upon the receipt of a byte the UART can generate an interrupt to which the software responds by quickly taking the received byte and shoves it onto the end of the buffer.

2) Background software routines can then regularly check if the buffer has anything in it yet and empty it as required.

As the circular buffer size can be defined pre-compilation the size is then limited. This helps improve space efficiency and should eliminate memory corruption at a trade off to how many bytes can be received before data starts to become lost.

阪姬 2024-09-03 09:52:40

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

如果没有循环缓冲区,执行此操作(C 风格)的一种昂贵机制是拥有一个包含 100 个元素的数组。每次计算新的成本时,您可以将 99 个元素向下移动并将新元素放在最后一个位置。这显然是代价高昂的。使用循环缓冲区的想法,您只需跟踪缓冲区的“末尾”(位置 0-99)。它将标记最旧(或最新……无论您选择哪个)成本项目的位置。读取旧值(用于更新运行平均值)后,将其替换为最新值并增加缓冲区位置(如果它位于 99,则将其设置回 0……因此,即圆形部分)。

将它与双向链表进行比较并没有什么意义。循环缓冲区当然可以用双向链表(甚至单链表)来实现。但可以这么说,比较它们有点像比较苹果和橘子。

A circular buffer is a nice mechanism for efficiently maintaining a sliding/moving list of values/items in an ordered fashion. One example might be to maintain a sliding average of the last N items. Suppose you want to track the average cost of the last 100 operations of computing some value. To do this, you would need to remove the oldest cost and add in the newest cost.

Without a circular buffer, a costly mechanism for doing this (C style) would be to have an array of 100 elements. Each time a new cost is computed, you could memmove the 99 elements down and put the new one in at the last position. This is obviously costly. Using a circular buffer idea, you would just track the “end” of the buffer (position 0-99). It would mark the position of the oldest (or newest … whichever you choose) cost item. After reading the old value (for updating the running average), you replace it with the newest value and increment the buffer position (if it is at 99, you set it back to 0 … thus, the circular part).

Comparing it to a doubly linked list doesn’t really make sense. A circular buffer could certainly be implemented with a doubly linked list (or even a singly linked list). But comparing them is a little bit like comparing apples and oranges so to speak.

奢欲 2024-09-03 09:52:40

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

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

循环缓冲区、循环缓冲区或
环形缓冲区是一种数据结构
使用单个固定大小的缓冲区,就像
它是端到端连接的。这
结构很容易
缓冲数据流

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

关于与双链表相比,我想它确实取决于您使用列表的目的......循环缓冲区的实现似乎更复杂,请(再次)参考维基页面;这解释了实现、注意事项等,并显示了示例代码。

谢谢,尼尔

I know this is cheating, but wikipedia does have a very good explaination.

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

A circular buffer, cyclic buffer or
ring buffer is a data structure that
uses a single, fixed-size buffer as if
it were connected end-to-end. This
structure lends itself easily to
buffering data streams

An example that could possibly use an
overwriting circular buffer is with
multimedia. If the buffer is used as
the bounded buffer in the
producer-consumer problem then it is
probably desired for the producer
(e.g., an audio generator) to
overwrite old data if the consumer
(e.g., the sound card) is unable to
momentarily keep up. Another example
is the digital waveguide synthesis
method which uses circular buffers to
efficiently simulate the sound of
vibrating strings or wind instruments.

With regards comparing to double-linked lists, I imagine it really does depend on what you are using the list for... Implementation of cirular buffers seems to be more complex, please (again) refer to the wiki page; this explains implementation, considerations etc and also shows example code.

Thanks, Neil

且行且努力 2024-09-03 09:52:40

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

I've used it as an easy way of implementing round-robin scheduling. Basically I had a bunch of different objects that can produce a value that a consumer could then process. I stuck all the producers in a ring and asked each one in turn.

囍笑 2024-09-03 09:52:40

我在多线程代码中使用了环形缓冲区。基本上,如果所有插槽都已满,则生产者必须等待。消费者只需处理“已满”的槽中的物品即可。

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

.NET 多线程变量访问

I have used a ring buffer in multi-threaded code. Basically, if all slots are full the producer(s) have to wait. The consumers simply process items in slots that are "full".

Here's a thread I started on it. It has some good advice on implementation.

.NET multi-threaded variable access

晌融 2024-09-03 09:52:40

我认为最消耗精力的答案是,“当您想要按创建顺序读取顺序生成的数据时,执行内存敏感任务,并且不关心第 n 个到最后一个接收数据之外的旧数据。”

I think the all-consuming answer is, "memory sensitive tasks when you want to read sequentially generated data in order of creation, and don't care about old data beyond the nth to last received datum."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文