【问题标题】:Efficient Java Serialization: Using ByteOutputArrayStream?高效的 Java 序列化:使用 ByteOutputArrayStream?
【发布时间】:2015-03-16 02:44:01
【问题描述】:

我一直在努力寻找一种有效的方法来序列化特定类以在我的服务器和客户端之间传递,并且一直在使用ByteOutputArrayStream 来传递字节数组。但是,this article 让我想知道我是否应该使用 ByteOutputArrayStream。这是我用来序列化和反序列化一个名为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();
}

PackagedData 类看起来像:

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;
  }
}

我的两个问题是:我应该使用 ByteArrayOutputStream 吗?如果是这样,我应该在参数中将缓冲区大小设置为什么?我了解 ByteArrayOutputStream 会根据需要增加缓冲区大小,但我认为这将比一开始以适当的缓冲区大小初始化它需要更多的资源和时间。

提前谢谢你。

【问题讨论】:

  • ByteArrayOutputStream 很好,而且几乎可以肯定不是这段代码的瓶颈——当然,你可以在这里消除它。 真正 很糟糕的是本机 Java 序列化,在速度和输出大小方面都应该避免。 github.com/eishay/jvm-serializers/wiki
  • @MattBall 啊,我明白了。由于我使用的 API,我无法真正避免该项目中的 Java 序列化,但是您对我在第一次初始化时设置 ByteArrayOutputStream 的参数的值有什么建议吗?或者默认的 32 缓冲区大小可以吗?将存储在Packaged Data 中的键/值的大小没有限制,并且键/值的类类型甚至可能在以后随着代码的发展而改变。
  • 如果发现ByteArrayOutputStream 是您代码中的瓶颈,我会感到非常惊讶。与任何性能问题一样:您必须衡量。
  • ByteArrayOutputStream冗余的。 它增加了延迟。这实际上是在浪费时间空间。

标签: java serialization bytearrayoutputstream


【解决方案1】:

如果你想让你的对象Serialization 更有效率,我强烈建议你用类似的东西来实现Externalizable

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();
    }
}

如果序列化 PackageData 是真正关键的代码,您应该会看到显着的性能改进。

【讨论】:

  • 感谢您的建议!我会试试看。但是,我关于ByteOutputArrayStream 的缓冲区大小的问题仍然存在。我将如何确定正确的初始缓冲区大小?除了类类型之外,键/值大小没有真正的限制,甚至类类型也可能在以后随着代码的发展而改变。默认缓冲区大小 32 可以吗?
  • @Platypi 我认为ByteArrayOutputStream 并不重要;为您的代码和实验添加基准。你也可以用BufferedOutputStream 包装它(但我怀疑它不会产生重大影响)。
  • 如果您的valueint,即不为空,这将比Integer 好得多。
猜你喜欢
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 2012-10-24
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 2017-04-14
  • 2011-10-05
相关资源
最近更新 更多