JavaLambdaInternals icon indicating copy to clipboard operation
JavaLambdaInternals copied to clipboard

在使用steam并行的计算时候,出现了oom

Open xueding-e opened this issue 6 years ago • 4 comments

感谢您的科普,我也顺利用上了流。 在实际使用并行流的时候遇到了一个oom。 大致情况是要处理一个四十多m的txt文件,内容为换行的字符串。 使用lines.flatMap(line -> Arrays.stream(line.split(" "))).parallel().distinct().count();做并发计算词语个数(数量大概在三百万,类似 一@一对一 5 一@一道 5 一@丁 6 一@七旬 8 一@万 157)。 执行期间,并行流吃光了我的内存,cpu,我jvm中的old跟eden全部爆满,方法区正常,线程正常。 串行与外部迭代只会吃掉五十m内存。

请教作者,是我并发流用的不对,还是jdk8的流有bug ---下面是重现代码 static void useStream(){ long uniqueWord = 0; try (Stream<String> lines = Files.lines(Paths.get("D:\nlp\dictionary\CoreNatureDictionary.ngram.txt"), Charset.defaultCharset())){ long start = System.currentTimeMillis(); uniqueWord = lines.flatMap(line -> Arrays.stream(line.split(" "))).parallel().distinct().count(); // uniqueWord = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count(); System.out.println(uniqueWord); long end = System.currentTimeMillis(); System.out.println("耗时"+ (end-start)+"ms"); }catch (IOException e){ e.printStackTrace(); } }

xueding-e avatar Dec 16 '19 06:12 xueding-e

这是缩减后的文件,只有10m,依旧会引起我2g jvm的oom CoreNatureDictionary.ngram.txt

xueding-e avatar Dec 16 '19 07:12 xueding-e

像是forkjoin导致内存复制的原因,建议直接输出forkjoin线程池内各内存分布看一下,应该就清楚原因了

vincentruan avatar Apr 20 '20 14:04 vincentruan

像是forkjoin导致内存复制的原因,建议直接输出forkjoin线程池内各内存分布看一下,应该就清楚原因了

这样并行流不能用了哦,200倍的内存都吃完了

xueding-e avatar Apr 22 '20 06:04 xueding-e

这样并行流不能用了哦,200倍的内存都吃完了 通过运行你的代码,我这边(jdk版本是1.8.0_144)设置的jvm参数:-Xmx1024m -Xms1024m,发现是能运行成功得出结果的,多次运行平均耗时5000~6000ms,但是串行流的时间只有它的十分之一。按照我的理解,并行流的使用场景是CPU密集型的,你这个场景应该是不太适用。测试代码如下: public static void main(String[] args) { long uniqueWord; Path path = Paths.get("C:\\Users\\DELL\\Downloads\\CoreNatureDictionary.ngram.txt"); try (Stream<String> lines = Files.lines(path, Charset.defaultCharset())) { long start = System.currentTimeMillis(); uniqueWord = lines.flatMap(line -> Arrays.stream(line.split(" "))).parallel().distinct().count(); // uniqueWord = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count(); System.out.println(uniqueWord); long end = System.currentTimeMillis(); System.out.println("耗时" + (end - start) + "ms"); } catch (IOException e) { e.printStackTrace(); } }

xiajiafu avatar Oct 09 '20 09:10 xiajiafu