java - Netty 使用来自池化直接 ByteBuf 的 ByteBuffer
问题描述
我试图了解有关 netty 的 ByteBuf 及其与 nio.ByteBuffer 的关系的一些事情。
我试图解决的问题是我的服务器必须返回位于服务器上的文件的随机部分——这是使用 nio.FileChannel 实现的,而 FChannel 取决于 nio.ByteBuffer。
据我了解,分配直接 ByteBuffer 应该是池化的 - 但 nio 中没有本机池实现 - 我的应用程序应该添加这样的层,所以我不会为每个请求创建直接缓冲区而付出代价。
我的应用程序使用 netty 作为服务器,所以我认为我可以使用 netty 的池化直接 ByteBuff 并访问它使用的 ByteBuffer
var byteBuf = ctx.alloc().directBuffer(1024); // (1)
var chunkHolder = byteBuf.nioBuffer(0, byteBuf.capacity()); // (2)
所以一切都按预期工作,但.nioBuffer
或.nioBuffers
创建缓冲区的副本 - 不仅仅是 ByteBuff 上的视图,因此在写入chunkHolder
位置/限制/等后byteBuf
保持不变!
我必须使用
var flip = chunkHolder.flip(); // (2)
var content = Unpooled.wrappedBuffer(flip);
ctx.writeAndFlush(content)
.addListener(f -> byteBuf.release()); (1)
所以再次创建对象,唯一的好处是没有复制该内存-如果我没记错的话。
问题:我可以做一些更聪明的事情,以便在 tcp 传输和文件读取之间没有数据复制,并且垃圾最少?nio 是否有助于维护直接的 ByteBuffers?
我想到的最好的想法是用类似 ByteBuffer 的实现包装 BytBuf,并将所有写操作代理回底层 byteBuf。
PS:我也看过io/netty/channel/DefaultFileRegion.java
它与 nio.FileChannel 一起使用,但在幕后 netty 直接使用 nio
raf = new RandomAccessFile(filePath, "r");
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, length));
解决方案
FileRegion 将为您进行零拷贝传输,因为它在FileChannel#transferTo()
内部使用 JDK。在这种情况下,这将是产生最少垃圾的途径。
推荐阅读
- android - Jetpack Compose LazyRow 滚动仅与下一个或上一个元素开始
- c++ - 2D 网格旅行(动态编程) - 递归解决方案工作但没有记忆之一
- typescript - 带有实例键的约束参数
- c# - 如何通过 PythonNet 在 C# 中创建 python def 函数
- python - 应用我的函数 if...else 条件语句不通过
- python - 从一个包含单词及其情绪的文本文件中,我尝试使用 python 仅打印表达悲伤情绪的单词。有人请帮助我
- mysql - nodejs查询中的错误:列数与值数不匹配
- python - 将元组列表的字典解包到位
- django - 使用 MongoDB 重置 Django 密码 - DatabaseError 没有异常消息
- ios - React-native:未定义符号:_swift_getFunctionReplacement