减少许多字符串的垃圾收集器开销

时间:2014-09-09 03:57:00

标签: java string garbage-collection

我正在构建一个百万行电子表格,在这个过程中完成的任何事情,一百万次,都可以大大增加。我遇到的一个问题是当我在单元格中处理公式时,我必须解析公式,调整引用,然后重新构建公式。在这个过程中,我创建了5到12个字符串(取决于标记化时有多少个对象),然后我就完成了。

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

有没有减少GC命中的方法? (如果这是C ++,我只会创建一个字符串池来重用。)

细节:

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

在处理过程中,为短期使用创造了大量的字符串。它杀死我的情况是调整细胞配方的地方。模板在几个单元格中有一个公式,类似于“= A5 + A6”,然后根据每行的位置进行调整。我解析出对象{“A5”,“+”,“A6”},调整它们现在所在的行,然后在StringBuilder中将所有这些放回到StringBuilder中,并将toString()分配回来到单元格中的公式String对象。

将大多数文档对象写入磁盘的困难在于文档对象不会被读取,操作和写出新文档对象。为了减少内存命中并处理我们需要遍历列而不是行的情况,我们处理对象,就像调整它一样。

问题是当我们内存不足时 - 整个事情都会超速运行直到我们达到这一点。我正在使用YourKit进行分析,并且它正在收集它正在收集String对象。传递StringBuilder对象可以帮助一点但不是很多,因为我将收集很多这些(更少,但仍然很多)。

2 个答案:

答案 0 :(得分:3)

此命中使IMHO与处理数百万字符串无关。我刚刚测量到我可以创造每秒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] 

答案 1 :(得分:2)

内存中的对象太多,意味着垃圾收集器的清理工作太多了。我相信如果您使用StringBuilder / StringBuffer而不是String,可以减少创建的对象数量。无论何时操作String对象,都会因为String的不可变特性而创建一个新对象。

但是如果使用StringBuilder / StringBuffer来操作字符串,则不会创建新对象。 StringBuilder / StringBuffer会动态调整大小,但如果您选择StringBuilder / StringBuffer的初始大小,也可以限制它。

简而言之,垃圾收集器需要较少的对象,较少的工作。