Hello Core Libs Dev Team,

I have a file that I am streaming from a service, and I am trying to split
into multiple parts based on a certain attribute found on each line. I am
sending each part up to a different service.

I am using BufferedReader.lines(). However, I cannot read the whole file
into memory because it is larger than the amount of RAM that I have on the
machine. So, since I don't have access to Java 22's Preview Gatherers Fixed
Window, I used the iterator() method on my stream, wrapped that in another
iterator that can grab my batch size worth of data, then built a
spliterator from that that I then used to create a new stream. In short,
this wrapper iterator isn't Iterator<T>, it's Iterator<List<T>>.

When I ran this sequentially, everything worked well. However, my CPU was
low and we definitely have a performance problem -- our team needs this
number as fast as we can get. Plus, we had plenty of network bandwidth to
spare, so I had (imo) good reason to go use parallelism.

As soon as I turned on parallelism, the stream's behaviour changed
completely. Instead of fetching the batch and processing, it started
grabbing SEVERAL BATCHES and processing NONE OF THEM. Or at the very least,
it grabbed so many batches that it ran out of memory before it could get to
processing them.

To give some numbers, this is a 4 core machine. And we can safely hold
about 30-40 batches worth of data in memory before crashing. But again,
when running sequentially, this thing only grabs 1 batch, processes that
one batch, sends out the results, and then start the next one, all as
expected. I thought that adding parallelism would simply make it so that we
have this happening 4 or 8 times at once.

After a very long period of digging, I managed to find this link.

https://stackoverflow.com/questions/30825708/java-8-using-parallel-in-a-stream-causes-oom-error

Tagir Valeev gives an answer which doesn't go very deep into the "why" at
all. And the answer is more directed to the user's specific question as
opposed to solving this particular problem.

After digging through a bunch of other solutions (plus my own testing), it
seems that the answer is that the engine that does parallelization for
Streams tries to grab a large enough "buffer" before doing any parallel
processing. I could be wrong, and how large that buffer is? I have no idea.

Regardless, that's about where I gave up and went sequential, since the
clock was ticking.

But I still have a performance problem. How would one suggest going about
this in Java 8?

Thank you for your time and help.
David Alayachew

Reply via email to