2

I'm utilizing a third party binary encoder that takes an OutputStream. I retrieve the OutputStream from a Marshallable's writeMarshallable method similar to this:

public void writeMarshallable(WireOut wire) {
    OutputStream outputStream = wire.bytes().outputStream();
    // third party code gets the outputStream, etc.
}

wire.bytes().outputStream()'s implementation creates a new StreamingOutputStream on each invocation, which is what I'm hoping to avoid (superfluous object allocation when the underlying Bytes hasn't actually changed).

That said, I'm thinking about storing a WeakReference to the given wire.bytes() value and checking to see if the provided value reference (ie, ==) is identical to the previously provided value:

private WeakReference<Bytes<?>> priorBytesRef = new WeakReference<>(null);

public void writeMarshallable(WireOut wire) {
    Bytes<?> bytes = wire.bytes();
    if (bytes != priorBytesRef.get()) {
        priorBytesRef = new WeakReference<>(bytes);
        thirdPartyEncoder = EncoderFactoryExample.from(bytes.outputStream());
    }
    // utilize thirdPartyEncoder, etc.
}

So my question is whether this is a reasonable approach or if you Chronicle folks have a more advisable way?

thanks!!

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
A. Oswald
  • 21
  • 2

1 Answers1

0

I suggest using a ThreadLocal to save a StreamingOutputStream.

static final ThreadLocal<StreamingOutputStream> bosTL = ThreadLocal.withInitial(StreamingOutputStream::new);

public void writeMarshallable(WireOut wire) {
    OutputStream out = bosTL.get().init(wire.bytes());
    // utilize thirdPartyEncoder, etc.
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • If the Marshallable's allocation is by way of a ServiceWrapper (ie, it's a _single_ allocation managed by the ServiceWrapper), is the ThreadLocal necessary or can I just get away with a BytesOutputStream _class member_? Thanks again, Pete! – A. Oswald Dec 26 '16 at 15:57
  • @A.Oswald The ThreadLocal is only needed if you can't be sure only one thread will be using the stream. – Peter Lawrey Dec 26 '16 at 18:03
  • Unless I've got either versioning or dependency goofed up, I'm afraid there's a conflict of Bytes _type_ being provided by Chronicle-Queue (net.openhft.chronicle.bytes) vs what BytesOutputStream's api requires (net.openhft.lang.io). I was getting BytesOutputStream from OpenHFT/Java-Lang (v 6.8.2). – A. Oswald Dec 27 '16 at 14:48
  • Pete: **code does not compile**; please see my above comment regarding Bytes type incompatibility. Any thoughts? thanks – A. Oswald Jan 03 '17 at 13:57
  • @A.Oswald I suggest avoiding Java-Lang as this is an older library. I suggest using Chronicle-Bytes which is what Chronicle-Queue uses. – Peter Lawrey Jan 03 '17 at 14:03
  • At first I felt a bit foolish, but after checking, BytesOutputStream (currently) _does not exist_ in **Chronicle-Bytes**. Can you please double check this? – A. Oswald Jan 03 '17 at 17:22
  • @A.Oswald Sorry, that is my mistake, you are right, the class was renamed. Can you check out the latest snapshot for `StreamingOutputStream`. If you are happy with that I can release it. – Peter Lawrey Jan 03 '17 at 17:46
  • Are you suggesting calling StreamingOutputStream's _init_ on each invocation? I'm not terribly fond of the method name, but everything else appears to look good (and I don't have a better suggestion). Thanks for looking into this! Ps: the code example will need to change from _bytes_ to whatever you end up calling it (currently _init_) – A. Oswald Jan 03 '17 at 18:21
  • @A.Oswald Yes, thank you for the correction. I use `init` as this is the name for constructors, at the byte code level constructors are called `` – Peter Lawrey Jan 03 '17 at 19:28