0

I have been working to find an efficient way to serialize a specific class to pass between my server and client and have been using ByteOutputArrayStream to pass around a byte array. However, this article makes me wonder if I should be using ByteOutputArrayStream at all. Here is the codec I use to serialize and deserialize a class called PackagedData:

public final PackagedData decode(final byte[] data) {
 final ByteArrayInputStream bstream = new ByteArrayInputStream(data);
 final PackagedData result;

 try (final ObjectInputStream ois = new ObjectInputStream(bstream)) {
     result = (PackagedData)ois.readObject();
 }catch (IOException | ClassNotFoundException e) {
     throw new RuntimeException(e.getCause());
 }
 return result;
}

public final byte[] encode(final PackagedData packagedData) {
  final ByteArrayOutputStream bstream = new ByteArrayOutputStream();

  try (final ObjectOutputStream oos = new ObjectOutputStream(bstream)) {
    oos.writeObject(packagedData);
  }
  catch (IOException e) {
    throw new RuntimeException(e.getCause());
  }
  return bstream.toByteArray();
}

The class PackagedData looks like:

public final class PackagedData implements Serializable {
  private final String dataType;
  private final String key;
  private final Integer value;

  public PackagedData(final String dataType, final String key, final Integer value) {
    this.dataType = dataType;
    this.key = key;
    this.value = value;
  }
  public final String getType(){
    return dataType;
  }
  public final String getKey() {
    return key;
  }
  public final Integer getValue() {
    return value;
  }
}

My two questions are: Should I use a ByteArrayOutputStream? If so, what should I set the buffer size to in the parameter? I understand ByteArrayOutputStream increases buffer size as needed but I figure that will just take more resources and time than initializing it at a proper buffer size in the first place.

Thank you in advance.

4
  • 1
    ByteArrayOutputStream is fine, and is almost certainly not the bottleneck in this code – though, sure, you could eliminate it here. What really sucks is the native Java serialization, and should be avoided, both in terms of speed and output size. github.com/eishay/jvm-serializers/wiki Commented Mar 16, 2015 at 2:50
  • @MattBall Ah I see. I can't really avoid the Java Serialization in this project because of the API I am using but do you have any suggestions as to what value I set the parameter of the ByteArrayOutputStream when I first initialize it? Or would the default 32 buffer size be alright? There is no limitation on the size of the key/value that will be stored in the Packaged Data and the class types of key/value may even change later as the code evolves. Commented Mar 16, 2015 at 2:59
  • 1
    I would be genuinely surprised if it turns out that ByteArrayOutputStream is the bottleneck in your code. As with any performance concern: you must measure. Commented Mar 16, 2015 at 3:05
  • The ByteArrayOutputStream is redundant. It adds latency. It is literally a waste of time space. Commented Mar 16, 2015 at 3:09

1 Answer 1

1

If you want to make your object Serialization more efficient, I strongly suggest you implement Externalizable with something like

public final class PackagedData implements Externalizable {
    private String dataType;
    private String key;
    private Integer value;

    public PackagedData(final String dataType, final String key,
            final Integer value) {
        this.dataType = dataType;
        this.key = key;
        this.value = value;
    }

    public String getType() {
        return dataType;
    }

    public String getKey() {
        return key;
    }

    public Integer getValue() {
        return value;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(this.dataType);
        out.writeUTF(this.key);
        out.writeInt(this.value);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        this.dataType = in.readUTF();
        this.key = in.readUTF();
        this.value = in.readInt();
    }
}

If serializing PackageData is truly critical code you should see significant performance improvements.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the suggestion! I will try it out. However, my question about the buffer size of ByteOutputArrayStream still stands. How would I determine the proper initial buffer size? There is no real limitation on what the key/value size will be other than its class type and even the class type may change later on as the code evolves. Would the default buffer size of 32 be okay?
@Platypi I don't think it matters much with a ByteArrayOutputStream; add a benchmark to your code and experiment. You might also wrap it with a BufferedOutputStream (but I suspect it won't make a significant difference).
If your value is an int i.e. not null, this would be much better than an Integer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.