RingBuffer vs Netty零拷贝

为什么会将这两个放在一起

原因是这两个缓存比较都是高性能,也比较容易联想到一起,容易搞混。

RingBuffer的原理

RingBuffer是Disruptor的核心组件,是一个高性能的队列

那么谈到队列,那么首先想到的就会是创建线程池使用的ArrayBlockingQueueLinkedBlockingQueue

那么这两个有什么缺点呢? 通过阅读代码我们可以得知,ArrayBlockingQueue内部结构是数组,
线程安全使用的锁,LinkedBlockingQueue的内部结构是双向链表,线程安全使用的也是锁。

我们都知道锁的性能是比较低下的,那么怎么能够保证更轻量级的实现线程安全呢?

答案就是CAS。

假如单个空间,单个空间的CAS去抢占,那么效率依然是低下的。那怎么能够减少抢的次数呢?

答案就是批量。多个联合一起去申请,这样就减少了CAS的次数,从而提高了效率。

这个就是RingBuffer的基本原理,CAS+批量申请。它还做了一些优化,如avaialbeBuffer(位置数组)来解决并发读的问题,伪共享解决(通过pad 7个long值避免核心的变量伪共享)。

synchronized是另外一种思路,一个乐观的思路,从轻到重自适应调整。

还有一些说法是ArrayBlockingQueue比LinkedBlockingQueue不仅性能好,而且对于GC也更友好。
我理解的原因是是否连续内存导致,连续内存一方面会容易发挥局部性原理,另一方面在GC扫描时区域也是连续的,效率会更高。

零拷贝

什么是零拷贝?

概念不知问wiki。

“Zero-copy” describes computer operations in which the CPU does not perform the task of copying data from one memory area to another. This is frequently used to save CPU cycles and memory bandwidth when transmitting a file over a network
零拷贝描述的是计算机在拷贝数据从一块内存区域到另外一块内存区域时,不必经过CPU。这是一个网络传输文件节省CPU的方式。

Linux的零拷贝

我们所有的服务基本都在Linux上,所以我们也了解一下Linux是如何做的。

Linux的实现主要是依赖DMA(Direct Memory Access)引擎,其实想想会比较简单。

  1. 如果CPU参与的话,CPU可能会控制指令、读取地址和目标地址。对于这种简单的工作,其实不需要CPU这样的参与,一个DMA引擎也可以完成。这样不仅节省了CPU的时间,也减少内核态和用户态的切换。
  2. 那DMA是不是可以将读取地址和目标地址合二为一呢? 相当于共用一块儿缓存,和RingBuffer的道理有点像,但是解决的不是一个问题。

所以基于DMA引擎,Linux实现了零拷贝。对外提供了transferTo方法。

Netty中零拷贝的实现

主要有以下几个方面:

  1. 直接使用堆外缓存。如果在 JVM 内部执行 I/O 操作时,必须将数据拷贝到堆外内存,才能执行系统调用。这是所有 VM 语言都会存在的问题。所以Netty直接使用堆外缓存,就避免了拷贝。
  2. ByteBuf。这个思想和DMA类似,是通过描述告诉读和写的位置,不再重新拷贝一次。
  3. FileRegion,利用的是系统的transferTo方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值