首先,原谅我做了标题党,但是内容还是值得一看的。
不少关于Netty
的文章和视频都表达一个意思,Netty
之所以牛逼其中一个原因就是因为它的零拷贝
机制。
那么这个零拷贝
到底是什么?根据我查阅资料,发现Netty
的零拷贝
体现在下面3个核心技术点,我们一起来看看真相吧!
可以和Netty零拷贝,扯上关系的第一个零拷贝就是Linux的零拷贝。我们用一个典型的文件传输案例来聊聊!
这个典型的案例中,经过了如下2步
这样没有问题,但是我们如果让这个数据不通过用户空间,直接在内核态进行数据填充了,效果是不是更好,看下图?
上面这种数据不经过用户空间,直接在内核空间填充的技术,就是零拷贝
。
Linux是提供了这类技术的,具体实现也有很多,这不是本文的重点,有兴趣的请自行谷歌。
Java的NIO
提供了一个API
叫做transferTo
,而Netty
也就在FileRegion
中简单的包裹了一下,具体可以参考该类io.netty.channel.DefaultFileRegion#transferTo
综上:关于文件的零拷贝,这不是Netty原创的零拷贝,还是要归功于NIO
的封装,当然最终还是要归功于系统!
第二个Netty
零拷贝相关的就是避C-Heap
和Java-Heap
的转换。
我们需要知道Java
读取文件流或者网络流,其底层都是native
的实现,就是说Java
调用了C
来实现的。
比如java.net.SocketInputStream#socketRead0
private native int socketRead0(FileDescriptor fd,
byte b[], int off, int len,
int timeout)
throws IOException;
比如java.io.FileInputStream#read0
private native int read0() throws IOException;
这种API调用方式,势必会导致C-Heap
到Java-Heap
的一层拷贝,这个是会耗费资源的。
NIO
本身就实现在堆外的内存DirectByteBuffer
,Netty的ByteBuf
也就是在这个上面封装了一层。我们来看看Netty
如何应用NIO
的DirectByteBuffer
来避免这一层C-Java
的拷贝的。
内存池的ByteBuf
创建的调用链路
io.netty.buffer.PooledByteBufAllocator#newDirectBuffer
io.netty.buffer.UnsafeByteBufUtil#newUnsafeDirectByteBuf
io.netty.buffer.UnpooledDirectByteBuf#UnpooledDirectByteBuf
io.netty.buffer.UnpooledDirectByteBuf#allocateDirect
java.nio.DirectByteBuffer#DirectByteBuffer(int)
综上:关于ByteBuffer
的零拷贝,不是Netty
原创还是要归功于NIO
这个才算是Netty
在零拷贝上的真实体现,原创精品,哈哈!
Composite
是复合
的意思,可以看出是复合ByteBuf
,这是一个NIO
的ByteBuffer的包装器。可以将实际上多个ByteBuf复合成逻辑上的一个ByteBuf
public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable < ByteBuf > {
private Component[] components; // resized when needed
private static final class Component {
final ByteBuf srcBuf; // the originally added buffer
final ByteBuf buf; // srcBuf unwrapped zero or more times
//这里:构造函数
Component(ByteBuf srcBuf, int srcOffset, ByteBuf buf, int bufOffset, int offset, int len, ByteBuf slice) {
//....
}
}
}
关键信息如上
Component[]
,每一个Component
又包含了ByteBuf
offset
很明显就是访问对应ByteBuf
时候的偏移量了Netty
在零拷贝
上的原创应该仅仅就是CompositeByteBuf
了,其他2处顶多是包装了下NIO
的特性。
但是你不能怀疑Netty
仍然是java
用的最广泛的网络通信
框架,绝对值得广大Javaer
学习