循环缓冲区有哪些用途?使用循环缓冲区有什么好处?它是否是双向链表的一种替代方法?
wko9yo5t1#
我已经用它来处理内存中的日志,它的大小是有限制的。例如,应用程序在处理用户请求时会写入日志条目。每当发生异常(这会中断处理),当前内存中的日志记录就会沿着转储。循环缓冲区的好处是,你不需要无限的内存,因为旧的条目会被自动覆盖。“挑战”是,你需要为你的用例找到一个合适的大小。在上面的例子中,如果包含关于异常的最重要信息的日志记录已经被覆盖,那将是非常不幸的。一些系统/应用程序有工具让您按需提取缓冲区的当前内容,而不仅仅是在自动提取时(如果有)。我相信ETW和CLR stress log,以及许多其他系统的内核或高性能跟踪/日志记录,都是这样实现的。使用这种缓冲区进行内存跟踪/日志记录的概念实际上是非常普遍的(不是说这是唯一的用途-当然不是),因为它比向文件/数据库写入记录快得多,除非发生错误,否则您可能永远不会对这些记录感兴趣。
kqlmhetl2#
循环缓冲区适用于嵌入式系统中的串行数据流。微控制器通常有一个UART来处理进入的串行字节,这些字节需要按顺序存储并稍后处理(字节进入的速度通常比它们可以处理的速度快)。缓冲器有效地将所需的时间关键响应(当字节进入时,以微秒计)分割为对整个消息的非时间关键响应(例如,以毫秒计显示进入的消息),例如:1)接收到字节后,UART可以生成中断,软件通过快速获取接收到的字节并将其推到缓冲器的末端来响应中断。2)然后,后台软件例程可以定期检查缓冲区中是否还有内容,并根据需要清空缓冲区。由于循环缓冲区的大小可以在预编译时定义,因此大小是有限的。这有助于提高空间效率,并应在数据开始丢失之前可以接收多少字节的权衡中消除内存损坏。
jljoyd4f3#
循环缓冲区是一种很好的机制,可以有效地以有序的方式维护值/项的滑动/移动列表。一个例子可能是维护最后N个项的滑动平均值。假设你想跟踪计算某个值的最后100次操作的平均成本。要做到这一点,你需要删除最旧的成本并添加最新的成本。如果没有循环缓冲区,则执行此操作的机制将非常昂贵(C风格)是有一个100个元素的数组。每次计算一个新的成本时,你可以将这99个元素下移,并将新的元素放在最后一个位置。这显然是代价很高的。使用循环缓冲区的思想,您只需跟踪缓冲区的“结尾”(位置0-99)。它将标记最老的(或最新的......无论您选择哪个)成本项目。阅读旧值后(用于更新移动平均值),您将其替换为最新值,并增加缓冲区位置(如果缓冲区位置为99,则将其设置回0......因此,循环部分)。将它与双向链表进行比较实际上没有意义。循环缓冲区当然可以用双向链表(甚至单向链表)来实现。但是,可以说,比较它们有点像比较苹果和桔子。
hpxqektj4#
我知道这是欺骗,但维基百科确实有一个很好的解释。http://en.wikipedia.org/wiki/Circular_buffer循环缓冲区、循环缓冲区或环形缓冲区是使用单个固定大小的缓冲区的数据结构,就好像它是端到端连接的一样。这种结构使其自身易于缓冲数据流一个可能使用覆盖循环缓冲区的例子是多媒体。如果缓冲区被用作生产者-消费者问题中的有界缓冲区,那么它可能是生产者所需要的(例如,音频发生器)来重写旧数据,如果消费者(例如,声卡)暂时不能跟上。另一个例子是数字波导合成方法,其使用圆形缓冲器来有效地模拟振动的弦乐器或管乐器的声音。关于与双向链表的比较,我想它确实取决于你使用列表的目的......循环缓冲区的实现似乎更复杂,请(再次)参考wiki页面;这解释了实现、注意事项等,并且还示出了示例代码。谢谢尼尔
gdx19jrr5#
我用它作为一种简单的方法来实现循环调度。基本上,我有一堆不同的对象,它们可以产生一个值,然后消费者可以处理。我把所有的生产者放在一个环中,依次询问每个生产者。
8ehkhllq6#
我在多线程代码中使用了一个环形缓冲区。基本上,如果所有的槽都满了,生产者必须等待。消费者只处理“满”的槽中的项目。这是我开始写的一个帖子,里面有一些很好的实施建议。.NET multi-threaded variable access
qyyhg6bp7#
我认为最令人头疼的答案是,“当您希望按照创建顺序读取连续生成的数据时,内存敏感型任务,而不关心从第n个到最后一个接收数据以外的旧数据。”
7条答案
按热度按时间wko9yo5t1#
我已经用它来处理内存中的日志,它的大小是有限制的。例如,应用程序在处理用户请求时会写入日志条目。每当发生异常(这会中断处理),当前内存中的日志记录就会沿着转储。
循环缓冲区的好处是,你不需要无限的内存,因为旧的条目会被自动覆盖。“挑战”是,你需要为你的用例找到一个合适的大小。在上面的例子中,如果包含关于异常的最重要信息的日志记录已经被覆盖,那将是非常不幸的。
一些系统/应用程序有工具让您按需提取缓冲区的当前内容,而不仅仅是在自动提取时(如果有)。
我相信ETW和CLR stress log,以及许多其他系统的内核或高性能跟踪/日志记录,都是这样实现的。
使用这种缓冲区进行内存跟踪/日志记录的概念实际上是非常普遍的(不是说这是唯一的用途-当然不是),因为它比向文件/数据库写入记录快得多,除非发生错误,否则您可能永远不会对这些记录感兴趣。
kqlmhetl2#
循环缓冲区适用于嵌入式系统中的串行数据流。微控制器通常有一个UART来处理进入的串行字节,这些字节需要按顺序存储并稍后处理(字节进入的速度通常比它们可以处理的速度快)。
缓冲器有效地将所需的时间关键响应(当字节进入时,以微秒计)分割为对整个消息的非时间关键响应(例如,以毫秒计显示进入的消息),例如:
1)接收到字节后,UART可以生成中断,软件通过快速获取接收到的字节并将其推到缓冲器的末端来响应中断。
2)然后,后台软件例程可以定期检查缓冲区中是否还有内容,并根据需要清空缓冲区。
由于循环缓冲区的大小可以在预编译时定义,因此大小是有限的。这有助于提高空间效率,并应在数据开始丢失之前可以接收多少字节的权衡中消除内存损坏。
jljoyd4f3#
循环缓冲区是一种很好的机制,可以有效地以有序的方式维护值/项的滑动/移动列表。一个例子可能是维护最后N个项的滑动平均值。假设你想跟踪计算某个值的最后100次操作的平均成本。要做到这一点,你需要删除最旧的成本并添加最新的成本。
如果没有循环缓冲区,则执行此操作的机制将非常昂贵(C风格)是有一个100个元素的数组。每次计算一个新的成本时,你可以将这99个元素下移,并将新的元素放在最后一个位置。这显然是代价很高的。使用循环缓冲区的思想,您只需跟踪缓冲区的“结尾”(位置0-99)。它将标记最老的(或最新的......无论您选择哪个)成本项目。阅读旧值后(用于更新移动平均值),您将其替换为最新值,并增加缓冲区位置(如果缓冲区位置为99,则将其设置回0......因此,循环部分)。
将它与双向链表进行比较实际上没有意义。循环缓冲区当然可以用双向链表(甚至单向链表)来实现。但是,可以说,比较它们有点像比较苹果和桔子。
hpxqektj4#
我知道这是欺骗,但维基百科确实有一个很好的解释。
http://en.wikipedia.org/wiki/Circular_buffer
循环缓冲区、循环缓冲区或环形缓冲区是使用单个固定大小的缓冲区的数据结构,就好像它是端到端连接的一样。这种结构使其自身易于缓冲数据流
一个可能使用覆盖循环缓冲区的例子是多媒体。如果缓冲区被用作生产者-消费者问题中的有界缓冲区,那么它可能是生产者所需要的(例如,音频发生器)来重写旧数据,如果消费者(例如,声卡)暂时不能跟上。另一个例子是数字波导合成方法,其使用圆形缓冲器来有效地模拟振动的弦乐器或管乐器的声音。
关于与双向链表的比较,我想它确实取决于你使用列表的目的......循环缓冲区的实现似乎更复杂,请(再次)参考wiki页面;这解释了实现、注意事项等,并且还示出了示例代码。
谢谢尼尔
gdx19jrr5#
我用它作为一种简单的方法来实现循环调度。基本上,我有一堆不同的对象,它们可以产生一个值,然后消费者可以处理。我把所有的生产者放在一个环中,依次询问每个生产者。
8ehkhllq6#
我在多线程代码中使用了一个环形缓冲区。基本上,如果所有的槽都满了,生产者必须等待。消费者只处理“满”的槽中的项目。
这是我开始写的一个帖子,里面有一些很好的实施建议。
.NET multi-threaded variable access
qyyhg6bp7#
我认为最令人头疼的答案是,“当您希望按照创建顺序读取连续生成的数据时,内存敏感型任务,而不关心从第n个到最后一个接收数据以外的旧数据。”