gpt4 book ai didi

java - 减少大量字符串的垃圾收集器开销

转载 作者:行者123 更新时间:2023-11-30 06:17:36 26 4
gpt4 key购买 nike

我正在构建一个百万行的电子表格,在这个过程中所做的任何事情,乘以一百万,加起来就会很成功。我遇到的问题之一是当我处理单元格中的公式时,我必须解析公式、调整引用,然后重新构建公式。在此过程中,我创建了 5 - 12 个字符串(取决于标记化时有多少对象),我使用这些字符串然后完成。

我发现垃圾收集器在此处理过程中占用了 70% 的时间,创建的主要对象然后超出要收集的范围是这些字符串。

是否有任何方法可以减少 GC 命中率? (如果这是 C++,我会创建一个字符串池以供重用。)

详情:

用于报告程序。我们读取模板,合并数据以生成最终报告,对最终报告进行处理,然后将其写入磁盘。该报告作为一个文档对象保存,在这种情况下,99% 是一个单一的表格,有 100 万行(当所有数据合并时),每行有 6 个单元格,每个单元格可选:一个公式,一个值,和/或格式化文本的正文。

在处理过程中,会创建大量字符串供短期使用。它杀死我的情况是调整单元格公式的地方。该模板在几个单元格中有一个公式,例如“=A5+A6”,然后根据每一行的位置进行调整。我解析出对象 {"A5"、"+"、"A6"},针对它们现在所在的行调整每个对象,然后在 StringBuilder 中将所有这些对象放回 StringBuilder 和要分配回的 toString()到单元格中的公式字符串对象。

大部分文档对象写入磁盘的难点在于,文档对象没有被读取、操作和写出一个新的。为了减少内存命中并处理我们需要遍历列而不是行的情况,我们在对象上进行适当的调整。

问题是当我们的内存不足时——在我们到达那个点之前,整个事情运行得非常快。我正在使用 YourKit 进行分析,它正在收集 String 对象。传递 StringBuilder 对象可能会有一些帮助,但不是很多,因为我将收集很多这样的对象(更少,但仍然很多)。

最佳答案

恕我直言,这次命中与处理数百万个字符串无关。我刚刚测得我每秒可以持续创建 600 万个字符串,而 GC 非常空闲。

问题似乎是您的内存不足。这使得 GC 工作得更频繁、更努力以保持程序运行。

所以不要浪费时间尝试降低分配率。

获取更多内存或减少消耗。获取更多内存通常是成本最低的方法。为了减少内存消耗,请考虑:

  • 处理数据,这样您就不需要同时将所有内容存储在内存中
  • 打包相同的数据。 char 占用 2 个字节,这意味着浪费了一半的内存(假设您主要使用 ASCII)。
  • 实习一些字符串。可能有很多短字符串重复了很多次...
  • 使用堆外内存。

没有你的程序,很难多说。

使用-XX:+PrintGCDetails-XX:+PrintGCTimeStamps。这就是我得到的 - nearly no GC overhead:

10.075: [GC [PSYoungGen: 442272K->896K(425472K)] 442852K->1476K(769024K), 0.0016600 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
10.323: [GC [PSYoungGen: 425344K->928K(409600K)] 425924K->1508K(753152K), 0.0017150 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
10.558: [GC [PSYoungGen: 409504K->928K(394240K)] 410084K->1508K(737792K), 0.0014760 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
10.791: [GC [PSYoungGen: 394144K->928K(379904K)] 394724K->1508K(723456K), 0.0017070 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

关于java - 减少大量字符串的垃圾收集器开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25736467/

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