RFR (L): 8058354: SPECjvm2008-Derby -2.7% performance regression on Solaris-X64 starting with 9-b29

Jon Masamitsu jon.masamitsu at oracle.com
Fri Jan 30 22:55:08 UTC 2015


Thomas,

Looks good.  Some throw-away suggestions.

Reviewed.

http://cr.openjdk.java.net/~tschatzl/8058354/webrev/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp.frames.html

>    75   BitMap::idx_t size_in_pages = align_size_up(rs.size(), commit_size) / commit_size;

Can you use round_to() in "share/vm/utilities/globalDefinitions.hpp"

> // returns integer round-up to the nearest multiple of s (s must be a 
> power of two)
> inline intptr_t round_to(intptr_t x, uintx s) {
>   #ifdef ASSERT
>     if (!is_power_of_2(s)) basic_fatal("s must be a power of 2");
>   #endif
>   const uintx m = s - 1;
>   return mask_bits(x + m, ~m);
> }

or change the name "size_in_pages" to "size_in_commit_pages"?

http://cr.openjdk.java.net/~tschatzl/8058354/webrev/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp.frames.html

Is  commit_int()

>   143 void G1PageBasedVirtualSpace::commit_int(char* start, char* end) {


short for commit_internal().  If yes, I find commit_internal() clearer.

http://cr.openjdk.java.net/~tschatzl/8058354/webrev/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp.frames.html

>    81   // Returns the address of the given page index ranging from 0..size_in_pages-1.
>    82   char*  page_end(uintptr_t index);

I'd change comment to

// Returns the address of the end of the page given the page index in range
// 0..size_in_pages-2.  For last page return _high_boundary.

   37 // We only support reservations which base address is aligned to a given commit
   38 // size. The length of the area managed need not commit size aligned (but OS default
   39 // page size aligned) because some OSes cannot provide a an os_commit_size aligned
   40 // reservation without also being size-aligned. Any tail area is committed using OS
   41 // small pages.

Is this below accurate?  If so, I'd suggest it.

// For systems that only allow commits of memory in a given size (always 
greater than the page size),
// the base address is required to be aligned to that commit size.  The 
actual size requested need not
// be aligned to the commit size, but the size of the reservation passed 
to the system may be rounded
// up to the commit size.   Any fragment (less than the commit size) of 
the actual size at the tail
// of the request, will be committed using OS small pages.

http://cr.openjdk.java.net/~tschatzl/8058354/webrev/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp.frames.html

Please verify that this should be a call to the _unaligned version.

> 1840   size_t const commit_size = os::page_size_for_region_unaligned(size, 1);


Jon

On 1/29/2015 2:30 AM, Thomas Schatzl wrote:
> Hi all,
>
>    can I have reviews for the following change that fixes the use of
> large pages for auxiliary data on G1?
>
> In JDK-8038423 there has been a large change in how G1 handles virtual
> memory, and overlooked that auxiliary data may use large pages. This
> caused some performance regressions after introducing that build.
>
> This change fixes this problem: G1 is now more flexible in using large
> pages: particularly auxiliary data that often is not sized to multiples
> of (large) page size suffers from that. By allowing the virtual space
> implementation to use small pages on the tail (upper) end of the virtual
> space, everything else can use large pages.
>
> There is one limitation to that: the start address of the used virtual
> spaces must be aligned to large page size to use large pages in
> auxiliary data. This is to simplify commit and uncommit within the
> regions, since very small areas in the auxiliary data can map to large
> areas in the heap (e.g. for the BOT, at 4k page size, one page maps to
> 2M of memory, 2M pages map to 1G of memory).
>
> The problem is, if the start address of such auxiliary data were not
> aligned to requested page size, we would potentially need to split
> neighbouring large pages if we tried to uncommit one.
>
> I.e. some ascii art showing the problem.
>
> AAAAAA AAAAAA AAAAAA  // heap area, each AAAAAA is a single region
>     |      |      |    // area covered by auxilary pages
>        1       2       // auxiliary data pages
>
> So if auxiliary data pages were unaligned, so that they correspond to
> uneven multiples of the heap, when uncommitting e.g. the second region
> (second set of AAAAAA), we would have to split the auxiliary data pages
> 1 and 2 into smaller ones.
>
> That does not seem to be a good tradeoff in complexity, given that the
> waste is at most one large page in reserved space (and unfortunately,
> due to the Linux large page implementation also in actually used space).
>
> Changes in detail containing some additional fixes:
>   - page selection corresponds to other collectors, i.e. if some
> auxiliary data covers at least one large page, try to use large pages if
> available.
>   - fix CMBitMap::compute_size() to align to alignment granularity (this
> has not been a real problem because the actual size is always a multiple
> of that)
>   - allow (very restricted) mixed use of small and large pages in the G1
> heap.
>   - pass on alignment hints to os::commit()
>   - some refactoring extracting out the code to reserve auxiliary memory
> structures
>
> With these changes, performance when using large pages is at least as
> good as before 9b29.
>
> Webrev:
> http://cr.openjdk.java.net/~tschatzl/8058354/webrev/
>
> CR:
> https://bugs.openjdk.java.net/browse/JDK-8058354
>
> Testing:
> jprt, specjbb*, specjvm*, vm.quick.testlist, some large benchmarks, test
> case
>
> Thanks,
>    Thomas
>
>



More information about the hotspot-gc-dev mailing list