qpid-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rafael Schloming <rafa...@redhat.com>
Subject Re: Use of AMQShortString in client side code
Date Wed, 19 Sep 2007 16:09:34 GMT
Robert Greig wrote:
> On 19/09/2007, Rafael Schloming <rafaels@redhat.com> wrote:
> 
>> At a minimum it would be nice if FieldTable implemented the Map
>> interface and had a copy constructor that took a regular Map.
> 
> In fact FieldTable used to be a subclass of HashMap (or AbstractMap or
> something like that). I cannot remember why that was changed now - Rob
> can you recall?
> 
>> This analysis gets a little more complicated in 0-10. In 0-10 a frame
>> boundary can appear anywhere, so it isn't possible to simply wrap the
>> bytes read in off the wire in an AMQShortString object and pass that up.
> 
> In a sense we have this today (if I understand you correctly) since
> you may only read a partial frame off the wire. That is a lower level
> obviously but is AFAICS exactly the same problem.

Yes, except 0-10 adds another level of this since frames are the unit 
you read off of the wire, and those can't be directly parsed without 
aggregating them. So for the 0-10 transport code you either end up doing 
two full copies if you want to provide contiguous byte buffers to the 
codec, or you make the codec deal with non contiguous byte buffers. I 
chose the latter, and also stopped using the CumulativeProtocolDecoder 
as there was no need anymore.

> I have discussed in the past using a special implementation of
> ByteBuffer that can aggregate sub byte buffers to avoid copying (that
> is currently done in the CumulativeProtocolDecoder or something like
> that).

I have something similar to this. It's not an implementation of 
ByteBuffer, it's just a Decoder object that knows how to read primitive 
AMQP types out of a list of multiple ByteBuffers. It's a bit simpler 
than a full ByteBuffer impl, but it has much the same effect.

>> You either need to copy the bytes into a newly allocated ByteBuffer, or
>> have a more sophisticated AMQShortString implementation that operates on
>> a list of fragments. Obviously it is impossible to do the latter if
>> AMQShortString is used directly throughout the code.
> 
> I don't follow the last sentence? AMQShortString would contain a
> subclass of ByteBuffer that under the hood was really multiple
> java.nio.ByteBuffer slices.

You're right, in theory I could modify or subclass the MINA ByteBuffer 
to provide this functionality. That is something I would rather avoid 
doing though as to date I've managed to keep MINA dependencies quite 
isolated.

>> I actually do want to expose a non JMS interface that doesn't use
>> AMQShortString. There is a lot of ground between providing an AMQP
>> specific messaging API and providing an AMQP specific String API.
> 
> And you want to postpone the creation of an AMQShortString? Your API
> layer could presumably hide that from the user of your API in the same
> way JMS does?

I actually don't want to bother going through AMQShortString at all. If 
the user passes me a String the most efficient thing for me to do is 
encode that directly onto the wire.

> Why does postponing the creation of the AMQShortString help? Are there
> cases where you might choose not to encode the string into a
> bytebuffer? Or are you avoiding the case of copying into a bytebuffer
> then copying that buffer into the buffer that contains the whole
> frame?

Yes, I'm avoiding that extra copy.

The other issue is that the generated API is at this point quite usable 
on its own, however usage of AMQShortString would make it unsuitable as 
a public API. So I'm forced to make something of a choice here, either 
generate code that is unusable as a public API, or generate code that is 
unusable by the broker because it is too slow.

That's why I'm trying to figure out if there are any options that 
satisfy both constraints, e.g. using CharSequence. It would make the 
generated code a whole lot more usable as a public API since on the 
input side you could just pass in a String directly without wrapping it, 
and it would permit the same optimized decoding that AMQShortString 
does. Obviously on the output side if you actually needed a concrete 
String you would still need to call toString(), but many of the java 
APIs will let you pass in a CharSequence anyways.

--Rafael

Mime
View raw message