不断增长的字节缓冲区
有没有人见过 java.nio.ByteBuffer 的实现,如果 putX() 调用超出容量,它将动态增长?
我想这样做的原因有两个:
- 我不知道提前需要多少空间。
- 我不想每次用完空间时都先执行 new ByteBuffer.allocate() 然后执行批量 put() 。
Has anyone has ever seen an implementation of java.nio.ByteBuffer that will grow dynamically if a putX() call overruns the capacity?
The reason I want to do it this way is twofold:
- I don't know how much space I need ahead of time.
- I'd rather not do a new ByteBuffer.allocate() then a bulk put() every time I run out of space.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
也值得看看 Netty 的 DynamicChannelBuffer。我发现方便的事情是:
slice(int index, int length)
It may be also worth to have a look at Netty's DynamicChannelBuffer. Things that I find handy are:
slice(int index, int length)
事实上,自动扩展缓冲区的使用起来更加直观。如果您能负担得起重新分配的性能奢侈,为什么不呢!
Netty 的
ByteBuf
为您提供了准确的信息这。就像他们已经采用了 java.nio 的ByteBuffer
并刮掉了边缘,使其更易于使用。此外,它是在Maven上的一个独立的
netty-buffer
包,因此您无需包含完整的 Netty 套件即可使用。Indeed, auto-extending buffers are so much more intuitive to work with. If you can afford the performance luxury of reallocation, why wouldn't you!?
Netty's
ByteBuf
gives you exactly this. It's like they've takenjava.nio
'sByteBuffer
and scraped away the edges, making it much easier to use.Furthermore, it's on Maven in an independent
netty-buffer
package so you don't need to include the full Netty suite to use.我建议使用输入流从文件接收数据(如果需要非阻塞,则使用单独的线程),然后将字节读入 ByteArrayOutstream,这使您能够将其作为字节数组获取。这是一个简单的示例,没有添加太多解决方法。
I'd suggest using an input stream to receive data from a file (with a sperate thread if you need non-blocking) then read bytes into a ByteArrayOutstream which gives you the ability to get it as a byte array. Heres a simple example without adding too many workarounds.
另一个解决方案是分配足够的内存,填充 ByteBuffer ,然后仅返回占用的字节数组:
初始化一个大的 ByteBuffer :
完成放置后但是
,从一开始就使用 org.apache.commons.io.output.ByteArrayOutputStream 可能是最好的解决方案。
Another solution for this would be to allocate more than enough memory, fill the
ByteBuffer
and then only return the occupied byte array:Initialize a big
ByteBuffer
:After you're done putting things into it:
However, using a
org.apache.commons.io.output.ByteArrayOutputStream
from the start would probably be the best solution.Netty ByteBuf 在这方面做得非常好。
Netty ByteBuf is pretty good on that.
Vector 允许持续增长
A Vector allows for continuous growth
要序列化某些东西,您将需要条目中的对象。您可以做的是将对象放入对象集合中,然后进行循环以获取迭代器并将它们放入字节数组中。然后,调用 ByteBuffer.allocate(byte[].length) 。这就是我所做的,它对我有用。
To serialize somethiing you will need object in entry. What you can do is put your object in collection of objects, and after that make loop to get iterator and put them in byte array. Then, call
ByteBuffer.allocate(byte[].length)
. That is what I did and it worked for me.为了使异步 I/O 工作,必须有连续的内存。在 C 中,您可以尝试重新分配数组,但在 Java 中,您必须分配新的内存。您可以写入
ByteArrayOutputStream
,然后在准备发送时将其转换为ByteBuffer
。缺点是您正在复制内存,而高效 IO 的关键之一是减少复制内存的次数。In order for asynchronous I/O to work, you must have continuous memory. In C you can attempt to re-alloc an array, but in Java you must allocate new memory. You could write to a
ByteArrayOutputStream
, and then convert it to aByteBuffer
at the time you are ready to send it. The downside is you are copying memory, and one of the keys to efficient IO is reducing the number of times memory is copied.ByteBuffer 不能真正以这种方式工作,因为它的设计概念只是特定数组的视图,您也可以直接引用该数组。它无法尝试将该数组交换为更大的数组而不发生奇怪的情况。
您想要使用的是
DataOutput
。最方便的方法是使用(预发布的)Guava 库:但您也可以从 ByteArrayOutputStream 手动创建 DataOutputStream,然后通过将虚假 IOException 链接到 AssertionError 来处理它们。
A ByteBuffer cannot really work this way, as its design concept is to be just a view of a specific array, which you may also have a direct reference to. It could not try to swap that array for a larger array without weirdness happening.
What you want to use is a
DataOutput
. The most convenient way is to use the (pre-release) Guava library:But you could also create a DataOutputStream from a ByteArrayOutputStream manually, and just deal with the spurious IOExceptions by chaining them into AssertionErrors.
另一种选择是使用具有大缓冲区的直接内存。这会消耗虚拟内存,但仅使用您使用的物理内存(按页,通常为 4K)
因此,如果您分配 1 MB 的缓冲区,它将消耗 1 MB 的虚拟内存,但唯一的操作系统将物理页提供给应用程序这是实际使用的。
结果是您看到您的应用程序使用了大量虚拟内存,但驻留内存相对较少。
Another option is to use direct memory with a large buffer. This consumes virtual memory but only uses as much physical memory as you use (by page which is typically 4K)
So if you allocate a buffer of 1 MB, it comsumes 1 MB of virtual memory, but the only OS gives physical pages to the application which is actually uses.
The effect is you see your application using alot of virtual memory but a relatively small amount of resident memory.
看看 Mina IOBuffer https://mina。 apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html 这是替换的下降(它包装了 ByteBuffer)
但是,我建议您分配比您需要的更多的内容,不用担心关于它太多了。如果您分配一个缓冲区(尤其是直接缓冲区),操作系统会为其提供虚拟内存,但它仅在实际使用时使用物理内存。虚拟内存应该非常便宜。
Have a look at Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html which is a drop in replacement (it wraps the ByteBuffer)
However , I suggest you allocate more than you need and don't worry about it too much. If you allocate a buffer (esp a direct buffer) the OS gives it virtual memory but it only uses physical memory when its actually used. Virtual memory should be very cheap.