应用程序不断接收命名Report
的对象并将对象放入Disruptor
三个不同的消费者。
在 Eclipse Memory Analysis 的帮助下,每个Report
对象的 Retained Heap Size 平均为 20KB。应用以 开头-Xmx2048
,表示应用的堆大小为 2GB。
但是,一次对象的数量约为 100,000 个,这意味着所有对象的总大小约为 2GB。
要求是所有 100,000 个对象都应加载到Disruptor
其中,以便消费者异步使用数据。但是如果每个对象的大小都大到 20KB 是不可能的。
所以我想将对象序列化String
并压缩它:
private static byte[] toBytes(Serializable o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return baos.toByteArray();
}
private static String compress(byte[] str) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(str);
gzip.close();
return new String(Base64Coder.encode(out.toByteArray()));
}
之后compress(toBytes(Report))
,对象尺寸变小:
压缩前
压缩后
现在对象的字符串大约是 6KB。现在好多了。
这是我的问题:
是否有任何其他数据格式的大小小于字符串?
每次调用序列化和压缩都会创建对象
ByteArrayOutputStream
,ObjectOutputStream
诸如此类。我不想创建很多类似的对象ByteArrayOutputStream
,ObjectOutputStream
因为我需要迭代 100,000 次。如何设计代码以便类似的对象ByteArrayOutputStream
只ObjectOutputStream
创建一次并在每次迭代中使用它?消费者需要反序列化和解压缩来自
Disruptor
. 如果我有三个消费者,那么我需要反序列化和解压缩三次。有什么办法吗?
更新:
正如@BoristheSpider 所建议的,序列化和压缩应该在一个动作中执行:
private static byte[] compressObj(Serializable o) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream zos = new GZIPOutputStream(bos);
ObjectOutputStream ous = new ObjectOutputStream(zos);
ous.writeObject(o);
zos.finish();
bos.flush();
return bos.toByteArray();
}