gpt4 book ai didi

java - 尝试使用将对象转换为字节数组时频繁GC

转载 作者:行者123 更新时间:2023-12-01 22:39:17 26 4
gpt4 key购买 nike

我正在使用下面的代码将对象转换为字节数组。

ByteArrayOutputStream baoS= new ByteArrayOutputStream();        
objectOutputStream ooS = new ObjectOutputStream(baoS);
ooS.writeObject(object);
ooS.flush();
ooS.close();
return baoS.toByteArray();

我们在生产环境中面临着频繁的GC问题和缓慢的问题。我们在运行时有很多对象,上面的代码将被调用以将对象转换为字节数组。如果频繁调用此代码是否会导致内存泄漏/更多 CPU 使用率?传递的对象是一个List。当使用 JVisualVM 完成采样时,此方法已成为瓶颈。

最佳答案

简单的解决方案是添加更多堆(如果可以的话)。根据请求量,这可能比支付工资来编写不同的解决方案更便宜。这样就无需更改代码、发布验证等。

The object passed is a List. This method has come as a bottleneck when sampling done with JVisualVM.

如果列表很大,那么堆上现在有两个巨大的东西:

  1. 列表
  2. 列表的字节数组版本

2 是骗人的。 ByteArrayOutputStream 中的默认缓冲区为 32 字节。大于该值的消息将导致创建另一个两倍大的数组并复制数据。如果不够大,请创建另一个数组并再次复制。等等等等。工作量很大!

现在对同时传入的所有请求并行执行此操作。然后,当所有工作完成后,您需要回收所有这些巨大的东西。这可以解释 gc。

下一个简单的解决方案是预先调整缓冲区的大小。如果您知道 98% 的消息大小小于 16k,那么您可以预先声明:new ByteArrayOutputStream(16384);。现在,从 32 字节增长到 16834 字节的所有数组副本中的 98% 都消失了。确实,这对于实际上很小的消息来说效率很低,但也许这是一个净胜。

或者不是固定的缓冲区大小,也许您可​​以猜测:new ByteArrayOutputStream(guessBufferSize(theList));

更困难的解决方案是,您可以尝试通过从堆中取出内容来缓解堆内存压力:将字节写入其他位置,例如写入磁盘上的临时文件并将文件路径发送到 jms 发送小部件。写入磁盘会使速度变慢,但这样做会减少堆抖动,从而使速度变快。

关于java - 尝试使用将对象转换为字节数组时频繁GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58507070/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com