forked from dodng/fast_ring_queue
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
root
committed
Jan 11, 2017
1 parent
a05865b
commit 104cd7a
Showing
1 changed file
with
10 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,19 @@ | ||
##1.环形队列是什么 | ||
##1. What is a circular queue | ||
|
||
队列是一种常用的数据结构,这种结构保证了数据是按照“先进先出”的原则进行操作的,即最先进去的元素也是最先出来的元素.环形队列是一种特殊的队列结构,保证了元素也是先进先出的,但与一般队列的区别是,他们是环形的,即队列头部的上个元素是队列尾部,通常是容纳元素数固定的一个闭环。 | ||
Queue is a common data structure, this structure ensures that the data is in accordance with the "first in first out" principle to operate, that is the first to go out of the elements is the first out of the element.Circular queue is a special queue structure , To ensure that the elements are FIFO, but the difference with the general queue is that they are circular, that is, queue head is the last element of the queue tail, usually a fixed number of elements to accommodate a closed loop. | ||
|
||
C代码实现见:https://github.com/dodng/fast_ring_queue | ||
##2. The advantages of circular queue | ||
|
||
###2.1. Guaranteed elements are first-in, first-out | ||
|
||
##2.环形队列的优点 | ||
###2.2. Element space can be reused | ||
|
||
###2.3. Provides an efficient mechanism for multithreaded data communication. | ||
|
||
###1.保证元素是先进先出的 | ||
##3. Circumstantial queue of work scenes | ||
|
||
是由队列的性质保证的,在环形队列中通过对队列的顺序访问保证。 | ||
(Linux system for PACKET_RX_RING and PACKET_TX_RING support in essence is a kernel to achieve a ring queue), such as the use of multi-threaded data transfer, | ||
|
||
##4. Actual test results | ||
|
||
###2.元素空间可以重复利用 | ||
|
||
|
||
|
||
因为一般的环形队列都是一个元素数固定的一个闭环,可以在环形队列初始化的时候分配好确定的内存空间,当进队或出队时只需要返回指定元素内存空间的地址即可,这些内存空间可以重复利用,避免频繁内存分配和释放的开销。 | ||
|
||
|
||
|
||
###3.为多线程数据通信提供了一种高效的机制。 | ||
|
||
在最典型的生产者消费者模型中,如果引入环形队列,那么生成者只需要生成“东西”然后放到环形队列中即可,而消费者只需要从环形队列里取“东西”并且消费即可,没有任何锁或者等待,巧妙的高效实现了多线程数据通信。 | ||
|
||
|
||
|
||
##3.环形队列的工作场景 | ||
|
||
一般应用于需要高效且频繁进行多线程通信传递数据的场景,例如:linux捕包、发包等等,(linux系统中对PACKET_RX_RING和PACKET_TX_RING的支持实质就是内核实现的一种环形队列) | ||
|
||
|
||
|
||
实际环形队列在工作时有3种情况: | ||
|
||
###3.1 入队速度=出队速度 | ||
|
||
这是环形队列的常态,即入队速度和出队速度大致一样,即使某个突然时刻入队速度陡然变高或者出队速度陡然变低,都能通过队列这个缓冲区把这些数据先存起来,等到能处理的时候再处理。 | ||
|
||
|
||
|
||
###3.2 入队速度>出队速度 | ||
|
||
在这种情况下,队列“写入”的速度>“读取”的速度,想象当这种状态持续一段时间之后,队列中大多数全是写入但没读取的元素,当又一个新的元素产生时,可以把这个新元素drop掉或者放在另一个缓冲区保存起来,这种情况的出现不是个好事情,说明你需要对出队处理元素的算法或逻辑优化处理速度了。 | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
###3.3 入队速度<出队速度 | ||
|
||
在这种情况下,队列“读取”速度>“写入”速度,这种情况说明程序出队处理元素的速度很快,这是比较好的情况,唯一不足的是读取队列的时候可能经常会轮询队列是否有新的元素,造成cpu占用过高。 | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
##4.无锁环形队列的实现 | ||
|
||
###4.1环形队列的存储结构 | ||
|
||
链表和线性表都是可以的,但几乎都用线性表实现,比链表快很多,原因也是显而易见的,因为访问链表需要挨个遍历。 | ||
|
||
###4.2读写index | ||
|
||
有2个index很重要,一个是写入index,标示了当前可以写入元素的index,入队时使用。一个是读取index,标示了当前可以读取元素的index,出队时使用。 | ||
|
||
###4.3元素状态切换 | ||
|
||
有种很巧妙的方法,就是在队列中每个元素的头部加一个元素标示字段,标示这个元素是可读还是可写,而这个的关键就在于何时设置元素的可读可写状态,参照linux内核实现原理,当这个元素读取完之后,要设置可写状态,当这个元素写入完成之后,要设置可读状态。 | ||
|
||
|
||
|
||
##5.实际测试效果 | ||
|
||
在CentOS 5.5 (cpu每核主频1200MHz)设备上简单测试了一下。环形队列大小为10000,元素数据大小为4字节,每秒可以写入并读取的元素是250万左右,即250pps. | ||
|
||
C代码实现见:https://github.com/dodng/fast_ring_queue | ||
In CentOS 5.5 (cpu per core frequency 1200MHz) on the device simply test a bit. The size of the ring queue is 10000, the size of the element data is 4 bytes, and the element that can be written and read per second is about 2.5 million, or 250 pps. |