Backports
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8216003 | 13 | Sangheon Kim | P4 | Resolved | Fixed | b03 |
JDK-8216125 | 12.0.1 | Sangheon Kim | P4 | Resolved | Fixed | master |
Description
This is sub-task for implementing the feature (JDK-8202286) for Parallel Scavenge GC.
Following text describes the design for ParallelScavenge GC. I have also attached basic class diagram and object diagram to explain the implementation.
To manage old generation in NV-DIMM, there are two levels at which we need enabling. First being the memory management level and second is at the GC level. At the memory management level we need to define new abstractions for VirtualSpace to manage memory which is backed by NV-DIMMs. At GC level we need to use the correct VirtualSpace abstractions and do additional handling to manage young and old generation.
ParallelScavenge takes 'ReservedSpace' corresponding to the Heap and creates 'AdjoiningVirtualSpaces' which comprises of two 'PSVirtualSpace's corresponding to the two generations. These virtual spaces are assigned to PSOldGen and PSYoungGen. 'AdjoiningVirtualSpace' maintains an internal boundary within the reserved heap space, lower part of it belongs to PSOldGen->PSVirtualSpace and higher part belongs to PSYoungGen->PSVirtualSpace.
Depending on value of AdaptiveGCBoundary flag there are two cases:
1. AdaptiveGCBoundary = false (default): In this case, the boundary in AdjoiningGenerations is fixed and each generation expands/shrinks within their respective reserved space. This case can be handled by creating a subclass of 'PSVirtualSpace' called 'PSFileBackedVirtualSpace' which manages memory exposed as filesystem (such as NV-DIMM). It has a file descriptor as its member and overrides calls to expand() and shrink() the virtual space.
2. AdaptiveGCBoundary = true: In this case, ParallelScavenge has more flexibility to size the generations. If the desired size of a generation is more than its reserved space, the boundary in 'AdjoiningVirtualSpaces' is moved to increase the reserved space for that generation. This case is a little tricky to implement, because adjusting the boundary would require changing physical memory mapping of the affected memory space (e.g. pages mapped to DRAM will be mapped to NV-DIMM). Such remapping is known to be very costly due to tlb miss penalties. To avoid this we need to have non-overlapping reserved memory space for old and young virtual spaces. We would need to reserve more than Xmx memory; reserved memory = (max_size_of_young + max_size_of_old). The young and old virtual spaces are assigned these non-overlapping reserved memories. To expand the committed memory of one virtual space, we need to shrink (uncommit) the other virtual space. In other words, we need an equivalent behaviour as adjust_boundary_up/down() calls in AdjoiningVirtualSpaces. To achieve this, we can implement a specialized implementation of 'AdjoiningGenerations' called 'AdjoiningGenerationsForHeteroHeap'. This implementation overrides calls such as adjust_boundary_*() and request_*_gen_expansion(). The overridden functionality maintains the invariant that total committed memory before and after expanding/shrinking of generations is same.
Following text describes the design for ParallelScavenge GC. I have also attached basic class diagram and object diagram to explain the implementation.
To manage old generation in NV-DIMM, there are two levels at which we need enabling. First being the memory management level and second is at the GC level. At the memory management level we need to define new abstractions for VirtualSpace to manage memory which is backed by NV-DIMMs. At GC level we need to use the correct VirtualSpace abstractions and do additional handling to manage young and old generation.
ParallelScavenge takes 'ReservedSpace' corresponding to the Heap and creates 'AdjoiningVirtualSpaces' which comprises of two 'PSVirtualSpace's corresponding to the two generations. These virtual spaces are assigned to PSOldGen and PSYoungGen. 'AdjoiningVirtualSpace' maintains an internal boundary within the reserved heap space, lower part of it belongs to PSOldGen->PSVirtualSpace and higher part belongs to PSYoungGen->PSVirtualSpace.
Depending on value of AdaptiveGCBoundary flag there are two cases:
1. AdaptiveGCBoundary = false (default): In this case, the boundary in AdjoiningGenerations is fixed and each generation expands/shrinks within their respective reserved space. This case can be handled by creating a subclass of 'PSVirtualSpace' called 'PSFileBackedVirtualSpace' which manages memory exposed as filesystem (such as NV-DIMM). It has a file descriptor as its member and overrides calls to expand() and shrink() the virtual space.
2. AdaptiveGCBoundary = true: In this case, ParallelScavenge has more flexibility to size the generations. If the desired size of a generation is more than its reserved space, the boundary in 'AdjoiningVirtualSpaces' is moved to increase the reserved space for that generation. This case is a little tricky to implement, because adjusting the boundary would require changing physical memory mapping of the affected memory space (e.g. pages mapped to DRAM will be mapped to NV-DIMM). Such remapping is known to be very costly due to tlb miss penalties. To avoid this we need to have non-overlapping reserved memory space for old and young virtual spaces. We would need to reserve more than Xmx memory; reserved memory = (max_size_of_young + max_size_of_old). The young and old virtual spaces are assigned these non-overlapping reserved memories. To expand the committed memory of one virtual space, we need to shrink (uncommit) the other virtual space. In other words, we need an equivalent behaviour as adjust_boundary_up/down() calls in AdjoiningVirtualSpaces. To achieve this, we can implement a specialized implementation of 'AdjoiningGenerations' called 'AdjoiningGenerationsForHeteroHeap'. This implementation overrides calls such as adjust_boundary_*() and request_*_gen_expansion(). The overridden functionality maintains the invariant that total committed memory before and after expanding/shrinking of generations is same.
Attachments
Issue Links
- backported by
-
JDK-8216003 Allocation of old generation of java heap on alternate memory devices - Parallel GC
-
- Resolved
-
-
JDK-8216125 Allocation of old generation of java heap on alternate memory devices - Parallel GC
-
- Resolved
-
- relates to
-
JDK-8202286 Allocation of old generation of Java heap on alternate memory devices
-
- Resolved
-