ringbuffer 消息队列 内存池 性能优化利器

性能优化利器

  • 简约而不简单的ringbuffer
    • ringbuffer数据结构
      • 用法
      • 工作机制
      • 区分缓冲区满或者空
    • 出色的KFIFO
    • ringbuffer蕴藏的巨大能量
      • 消息队列
      • 内存池
    • 总结

简约而不简单的ringbuffer

最近在研究srsLTE的代码,其中就发现一个有意思的数据结构——ringbuffer。
虽然,这是一个很基本的数据结构,但时,它在LTE这种通信协议栈系统中却大行其道,也是很容易被协议开发人员忽略的。在整个通信协议的开发团队中,一般会有一个平台中间件的团队,他们的任务是给业务部门提供高性能、高可靠性的中间件代码,如内存池、线程池、消息通信机制、日志系统等等。这篇文章就来讨论下这个简约而不简单的ringbuffer。

ringbuffer数据结构

环形缓冲器(ringr buffer),也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),圆形缓冲区(circula buffer),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。
在通信程序中,经常使用环形缓冲器作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。

下例为一个满的缓冲区的读写指针:

内存池

内存池在通信协议栈和很多的软件中都是常用的技术,它的好处是除了可以避免内存碎片,更重要的一点是,内存是预先申请的,并且自我管理,在申请和释放的效率更快,这对协议栈的实现是十分重要的。

内存池的实现在方式都是大同小异的,通常将内存分为8字节、16字节、32字节… 1K等大小不同的内存块,并通过链表的方式进行管理。具体的实现方式可以自行到github上搜索,实现方式都是类似的。

那么,ringbuffer和内存池有什么关系呢际上,ringbuffer和内存池的实现并无直接的关系,但是内存池在实现上有个至关重要的问题,那就内存的申请和释放可能不是在同一个线程中。简单的说就是,内存的申请和释放可能存在竞争的情况,通常的做法是进行加锁进行保护。但是加锁的操作可能对协议的时序产生不确定的影响,这对时序要求较高的协议实现(如CMAC)是无法接受的

ringbuffer的优秀的特性又一次被应用的淋漓尽致,做法也是相当的简单,就是使用ringbuffer单生产/单消费的模式的无锁特性,释放的线程可以将需要释放的地址使用ringbuffer发送给申请的线程,由申请的线程进行内存的释放,这就就不需要加锁的操作,因为同一个线程不会出现并发的链表操作
下图是结合了消息队列和内存池技术的一次应用,该方案是十分经典和有效的,在很多大型的通信系统中都能看到这种方案的影子:

ringbuffer 消息队列 内存池 性能优化利器

总结

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年3月22日
下一篇 2022年3月22日

相关推荐