Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
2.3.0
-
None
Description
I recently analyzed a heap dump of Yarn Node Manager that was suffering from high GC pressure due to high object churn. Analysis was done with the jxray tool (www.jxray.com) that checks a heap dump for a number of well-known memory issues. One problem that it found in this dump is 19.5% of memory wasted due to duplicate strings. Of these duplicates, more than a half come from FileInputStream.path and File.path. All the FileInputStream objects that JXRay shows are garbage - looks like they are used for a very short period and then discarded (I guess there is a separate question of whether that's a good pattern). But File instances are traceable to org.apache.spark.network.buffer.FileSegmentManagedBuffer.file field. Here is the full reference chain:
↖java.io.File.path
↖org.apache.spark.network.buffer.FileSegmentManagedBuffer.file
↖{j.u.ArrayList}
↖j.u.ArrayList$Itr.this$0
↖org.apache.spark.network.server.OneForOneStreamManager$StreamState.buffers
↖{java.util.concurrent.ConcurrentHashMap}.values
↖org.apache.spark.network.server.OneForOneStreamManager.streams
↖org.apache.spark.network.shuffle.ExternalShuffleBlockHandler.streamManager
↖org.apache.spark.network.yarn.YarnShuffleService.blockHandler
↖Java Static org.apache.spark.network.yarn.YarnShuffleService.instance
Values of these File.path's and FileInputStream.path's look very similar, so I think FileInputStream}}s are generated by the {{FileSegmentManagedBuffer code. Instances of File, in turn, likely come from
https://github.com/apache/spark/blob/master/common/network-shuffle/src/main/java/org/apache/spark/network/shuffle/ExternalShuffleBlockResolver.java#L258-L263
To avoid duplicate strings in File.path's in this case, it is suggested that in the above code we create a File with a complete, normalized pathname, that has been already interned. This will prevent the code inside java.io.File from modifying this string, and thus it will use the interned copy, and will pass it to FileInputStream. Essentially the current line
return new File(new File(localDir, String.format("%02x", subDirId)), filename);
should be replaced with something like
String pathname = localDir + File.separator + String.format(...) + File.separator + filename; pathname = fileSystem.normalize(pathname).intern(); return new File(pathname);
Attachments
Attachments
Issue Links
- is related to
-
SPARK-24938 Understand usage of netty's onheap memory use, even with offheap pools
-
- Resolved
-
- links to