[jboss-jira] [JBoss JIRA] (JGRP-2218) New buffers
Sanne Grinovero (JIRA)
issues at jboss.org
Tue Sep 12 04:31:00 EDT 2017
[ https://issues.jboss.org/browse/JGRP-2218?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13462492#comment-13462492 ]
Sanne Grinovero commented on JGRP-2218:
---------------------------------------
Great Goal!
bq. Instead of copying, the application creates an instance of Buffer and ...
I'd suggest to immediately encapsulate in the strategy of obtaining such a {{Buffer}} into some non-static service so that we can later introduce pooling and reuse.
The initial implementation could just create a new instance on each request and discard them on close, but then it will be easier in the future to experiment with alternative strategies and optimise some more details.
Call it {{BufferPool}} or {{BufferManagement}}, ... and every JGroups stack should start one.
The methods like {{acquire}} and {{release}} could be package private and visible only to the {{BufferPool}} ?
> New buffers
> -----------
>
> Key: JGRP-2218
> URL: https://issues.jboss.org/browse/JGRP-2218
> Project: JGroups
> Issue Type: Feature Request
> Reporter: Bela Ban
> Assignee: Bela Ban
> Fix For: 5.0
>
>
> h3. Goal
> Change payload in {{Message}} from byte[] arrays to a {{Buffer}} interface which can have multiple implementations.
> h3. Motivation
> Currently, having to pass a byte[] array to a message leads to unnecessary copying:
> * When an application has a ref to an NIO (direct) {{ByteBuffer}}, the bytes in the byte buffer have to be copied into a byte[] array and then set in the message
> * When the application sends around byte[] arrays, but also wants to add some additional metadata, e.g. type (1000-byte requests/responses), it needs to create a new byte[] array of (say) 1001 bytes and copy the data (1000 bytes) plus the request type (1 byte) into the new copy. Example: {{MPerf}} and {{UPerf}}
> h3. Design
> Instead of copying, the application creates an instance of {{Buffer}} and sets the buffer in {{Message}}. The {{Buffer}} is then passed all the way down into the transport where it is marshalled and sent. There can be a number of buffer implementations, e.g.
> * {{ArrayBuffer}}: wraps a byte[] array with an offset and length
> * {{NioDirectBuffer}}: wraps an NIO direct {{ByteBuffer}}
> * {{NioHeapBuffer}}: wraps an NIO heap-based {{ByteBuffer}}
> * {{CompositeBuffer}}: wraps multiple Buffers. E.g. type (1 byte) and data (1000 bytes) as described above
> * {{IntBuffer}}: a single integer
> * {{ObjectBuffer}}: has an Object and a ClassLoader (for reading), plus a Marshaller which know how to marshal the object, this allows for objects to be passed in buffers and they're only marshalled at the end (transport).
> * {{PartialBuffer}}: a ref to a {{Buffer}}, with an offset and length
> The {{Buffer}} interface has methods:
> * {{size()}}
> * {{writeTo(DataOutput)}}
> * {{readFrom(DataInput)}}
> * {{getInput()}}: this provides a {{DataInput}} stream for reading from the underlying buffer
> and possibly also
> * {{acquire()}} and
> * {{release()}} (for ref-counting).
> Each buffer impl has an ID and it should be possible to register new impls. A {{BufferFactory}} maintains a mapping between IDs and impl classes.
> When marshalling a {{Buffer}}, the ID is written first, followed by the buffer's {{writeTo()}} method. When reading buffers, the {{BufferFactory}} is used to create instances from IDs.
> h4. Fragmentation
> When fragmenting a buffer, the fragments are instances of {{PartialBuffer}} which maintains an offset and length over an underlying buffer. When marshalling a {{PartialBuffer}}, only the part between offset and offset+length is written to the output stream.
> h4. Reference counting
> If we implement ref-counting, then buffers can be reused as soon as the ref-count is 0. For example, when sending a message, the buffer's ref-count could be incremented by the app calling {{acquire()}}. (Assuming the message is a unicast message), {{UNICAST3}} would increment the count to 2. This is needed because {{UNICAST3}} might have to retransmit the message if it was lost on the network, and meanwhile the buffer cannot be reused (changed). The app calls {{release()}} when the {{JChannel.send()}} call returns, but the buffer cannot be reused until {{UNICAST3}} calls {{release()}} as well. This will happen when an {{ACK}} for the given message has been received.
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
More information about the jboss-jira
mailing list