我正在尝试运行一个可处理100M行记录的jar。我达到了GC超限。它可以正常工作10M。
我知道最好的办法是找到溢出发生的地方
我想尝试一次在服务器上运行jar,使其在堆内存,GC内存等上具有最大的资源。
我试图用-xms和-xmc来运行我的jar
java -Xmx256m -Xmc256m -jar myapp.jar //类似的东西
我想知道如何使用最大的资源运行,因为我没有将此服务器用于其他任何应用程序。
我也尝试使用此命令进行多线程
java -jar -Xmx30024m -XX:ParallelGCThreads = 12000 myapp.jar
但是我不确定这能起到多大作用。
有人可以建议我如何通过在命令行中进行一些有限的更改来克服GC错误,以在实例中使用最大的资源。
答案 0 :(得分:1)
问题与垃圾收集器无关,GC很快。仅当您已有no memory left时,GC才会引发此错误。除非记录很大,否则30GB绝对足以容纳1亿条记录。每条记录的大小是多少?我会尝试:
1)确保您具有64位Java,如果您偶然使用了32位Java,请重新运行代码
2)将对象拉出最内层循环/优化对象分配,即:使用.clear();不要做一个新的数组。将最有用的最内层循环分成几个不同的循环,每次迭代需要分配的对象数量更少。
3)尝试使您的工作递增,即使用mergesort而不是quicksort。这样,您可以在10M条记录输入的多个实例之间分配工作,并保存每个增量进度,然后再组合成100M条答案。
4)用C / C ++ / Rust对其进行编码,因此它使用堆栈而不是堆作为临时变量。如果在Java版本的最内层循环中的任何地方都不使用“ new”,那么您可能需要更多地压缩数据使用量。对5M,10M,15M记录的内存使用情况进行基准测试,以获取每个记录的每字节影响(经过这三个点的行的斜率),并查看是否可以想象是否可以用更少的字节来保存每个记录用系统语言分别控制每个字节(并查看该值是否仍小于您拥有的RAM)。
5)如果您的记录很大(> 1kb),则肯定要进行缓存。使用getter来访问每个记录,而不是直接从数组中访问,并限制内存使用量。让getter访问一个简单的100M引用数组,并将自己限制为其中90M个为NULL。如果在已使用10M的情况下尝试访问新记录,则在访问磁盘,缓存值并返回请求的记录之前,将随机/很少使用的现有记录设置为NULL。确保您的算法很好地适合这种缓存(要求3比建议3宽松,但原则上相同)。