是否存在允许动态增长和扩展 java.nio.ByteBuffer 的 ByteBuffer 实现?

Posted

技术标签:

【中文标题】是否存在允许动态增长和扩展 java.nio.ByteBuffer 的 ByteBuffer 实现?【英文标题】:Is there an implementation of ByteBuffer that allows for dynamic growing and extends java.nio.ByteBuffer? 【发布时间】:2019-06-16 15:30:16 【问题描述】:

我的代码中有一个 java.nio.ByteBuffer:

ByteBuffer bb = ByteBuffer.allocateDirect(1024);
... 

我希望能够将其替换为 ByteBuffer 的新实现(即它必须扩展 java.nio.ByteBuffer),以便它可以在后台重新分配、复制和丢弃以前的小 ByteBuffer , 以实现无缝的动态增长。

我不能只拥有一个包装器,因为它必须是 java.nio.ByteBuffer

应该是这样的:

ByteBuffer bb = new MyImplementationOfByteBufferThatExtendsByteBuffer(1024);

有人见过或做过吗?有可能吗?

只想注意,如果java.nio.ByteBuffer 是一个接口而不是一个抽象类,那么实现起来就很简单了。正如那句老话所说,如果您想要灵活性,请优先使用接口而不是抽象类

【问题讨论】:

Growing ByteBuffer的可能重复 我不认为它是重复的,因为该问题不需要字节缓冲区来扩展 java.nio.ByteBuffer。给出的所有答案都是包装。 ByteBuffer 的所有构造函数都是包私有的。所以可能没有“干净”的解决方案...... 或者实现你自己的github.com/wjtxyz/VarSizedByteBuffer 【参考方案1】:

不,这不存在,并且不能存在而不违反ByteBuffer的超类Buffer的约定:

缓冲区是特定原始类型元素的线性、有限序列。除了内容之外,缓冲区的基本属性还有容量、限制和位置:

缓冲区的容量是它包含的元素数。缓冲区的容量永远不会是负数,也永远不会改变。

因此,如果您允许“无缝动态增长”,ByteBuffer 将不再充当缓冲区。无论接口还是抽象类,这也是正确的:子类和接口实现都不应破坏它们扩展的类中定义的不变量。毕竟,您的 HypotheticalGrowingByteBuffer 的使用者可能依赖 Buffer 的固定容量来缓存对 capacity() 的单个调用,否则将被定义为不会更改。

使 ByteBuffer 成为抽象类而不是接口的另一个激励因素:支持缓冲区的内存被定义为必须固定且连续,这比更灵活的定义具有更高的性能。

也就是说,Buffer 定义了limit 的可变概念,其中最初分配的大型缓冲区可能会人为地限制其可用性。您可以使用它来约束大缓冲区从小开始然后增长,尽管增长不会“无缝”;它将受到您定义的原始缓冲区容量的限制。如果目标只是在整体总大小可预测的情况下连接较小的固定大小缓冲区,则可能值得使用ByteBuffer.duplicate 将它们生成为较大缓冲区的片段并设置 mark 和 limit 限制可写区域。

【讨论】:

【参考方案2】:

我很确定 ByteBuffers 具有固定容量是有意的。我鼓励您不要试图解决它,就好像它是一个设计缺陷一样。接受它并将其视为有目的的限制。

如果您允许 ByteBuffers 增长,那么 compact() 将不再具有可预测的最大运行时间。缓冲区越大,压缩它所需的时间就越长。我在基于 NIO 的套接字库中遇到了这个问题。我的内部缓冲区不断增长以适应大量数据注入,结果是性能下降与缓冲的数据量成正比。

例如,有人可能会尝试一次性发送 100MB 的数据,所以我会将这些数据保存在一个 100MB 的 ByteBuffer 中。处理代码一次只能处理大约 32KB,因此它会从缓冲区中提取 32KB 的数据,然后对其进行压缩。然后是另一个 32KB 和另一个压缩。它将继续读取和压缩,直到缓冲区耗尽。

每次压缩都是 O(n) 操作,我执行了 O(n) 很多操作,导致整体运行时间为 O(n2)。真是个坏消息。当缓冲区变得如此之大以至于 I/O 请求开始超时时,我注意到了这个问题,因为 I/O 线程一直在压缩 ByteBuffers。

解决方案:如果您需要动态缓冲区,请创建一个Queue<ByteBuffer>。队列可以增长并容纳无限数量的 ByteBuffer,而每个缓冲区保持固定大小。这将使您的应用程序正确扩展而不会遇到 O(n2) 问题。

【讨论】:

以上是关于是否存在允许动态增长和扩展 java.nio.ByteBuffer 的 ByteBuffer 实现?的主要内容,如果未能解决你的问题,请参考以下文章

如何查看和调试动态链接库的内存泄露

允许在同一页面上与用户聊天的 Chrome 扩展 [关闭]

vector的增长模式

阿里云 负载均衡

如何检查记录器是不是存在

csharp ObjectData扩展允许使用动态字典存储扩展任何.NET对象,GC将使用相关的ob收集它