Fri, 16 Jan 2015 10:29:12 +0100
8066875: VirtualSpace does not use large pages
Reviewed-by: stefank, tschatzl, anoll, thartmann
1.1 --- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Wed Nov 26 10:32:21 2014 -0800 1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Fri Jan 16 10:29:12 2015 +0100 1.3 @@ -66,9 +66,9 @@ 1.4 1.5 void GenerationSizer::initialize_size_info() { 1.6 trace_gen_sizes("ps heap raw"); 1.7 - const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8); 1.8 + const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8); 1.9 const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old 1.10 - const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages); 1.11 + const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages); 1.12 const size_t page_sz = MIN2(max_page_sz, min_page_sz); 1.13 1.14 // Can a page size be something else than a power of two?
2.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Wed Nov 26 10:32:21 2014 -0800 2.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Fri Jan 16 10:29:12 2015 +0100 2.3 @@ -55,7 +55,7 @@ 2.4 2.5 const size_t words = bits / BitsPerWord; 2.6 const size_t raw_bytes = words * sizeof(idx_t); 2.7 - const size_t page_sz = os::page_size_for_region(raw_bytes, 10); 2.8 + const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10); 2.9 const size_t granularity = os::vm_allocation_granularity(); 2.10 _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); 2.11
3.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Nov 26 10:32:21 2014 -0800 3.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jan 16 10:29:12 2015 +0100 3.3 @@ -401,7 +401,7 @@ 3.4 ParallelCompactData::create_vspace(size_t count, size_t element_size) 3.5 { 3.6 const size_t raw_bytes = count * element_size; 3.7 - const size_t page_sz = os::page_size_for_region(raw_bytes, 10); 3.8 + const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10); 3.9 const size_t granularity = os::vm_allocation_granularity(); 3.10 _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); 3.11
4.1 --- a/src/share/vm/memory/heap.cpp Wed Nov 26 10:32:21 2014 -0800 4.2 +++ b/src/share/vm/memory/heap.cpp Fri Jan 16 10:29:12 2015 +0100 4.3 @@ -100,8 +100,8 @@ 4.4 size_t page_size = os::vm_page_size(); 4.5 if (os::can_execute_large_page_memory()) { 4.6 const size_t min_pages = 8; 4.7 - page_size = MIN2(os::page_size_for_region(committed_size, min_pages), 4.8 - os::page_size_for_region(reserved_size, min_pages)); 4.9 + page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages), 4.10 + os::page_size_for_region_aligned(reserved_size, min_pages)); 4.11 } 4.12 4.13 const size_t granularity = os::vm_allocation_granularity();
5.1 --- a/src/share/vm/runtime/os.cpp Wed Nov 26 10:32:21 2014 -0800 5.2 +++ b/src/share/vm/runtime/os.cpp Fri Jan 16 10:29:12 2015 +0100 5.3 @@ -1315,15 +1315,17 @@ 5.4 return (sp > (stack_limit + reserved_area)); 5.5 } 5.6 5.7 -size_t os::page_size_for_region(size_t region_size, size_t min_pages) { 5.8 +size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) { 5.9 assert(min_pages > 0, "sanity"); 5.10 if (UseLargePages) { 5.11 const size_t max_page_size = region_size / min_pages; 5.12 5.13 for (size_t i = 0; _page_sizes[i] != 0; ++i) { 5.14 const size_t page_size = _page_sizes[i]; 5.15 - if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) { 5.16 - return page_size; 5.17 + if (page_size <= max_page_size) { 5.18 + if (!must_be_aligned || is_size_aligned(region_size, page_size)) { 5.19 + return page_size; 5.20 + } 5.21 } 5.22 } 5.23 } 5.24 @@ -1331,6 +1333,14 @@ 5.25 return vm_page_size(); 5.26 } 5.27 5.28 +size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) { 5.29 + return page_size_for_region(region_size, min_pages, true); 5.30 +} 5.31 + 5.32 +size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) { 5.33 + return page_size_for_region(region_size, min_pages, false); 5.34 +} 5.35 + 5.36 #ifndef PRODUCT 5.37 void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) 5.38 { 5.39 @@ -1579,17 +1589,17 @@ 5.40 5.41 static size_t large_page_size() { 5.42 const size_t large_page_size_example = 4 * M; 5.43 - return os::page_size_for_region(large_page_size_example, 1); 5.44 + return os::page_size_for_region_aligned(large_page_size_example, 1); 5.45 } 5.46 5.47 - static void test_page_size_for_region() { 5.48 + static void test_page_size_for_region_aligned() { 5.49 if (UseLargePages) { 5.50 const size_t small_page = small_page_size(); 5.51 const size_t large_page = large_page_size(); 5.52 5.53 if (large_page > small_page) { 5.54 size_t num_small_pages_in_large = large_page / small_page; 5.55 - size_t page = os::page_size_for_region(large_page, num_small_pages_in_large); 5.56 + size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large); 5.57 5.58 assert_eq(page, small_page); 5.59 } 5.60 @@ -1602,21 +1612,53 @@ 5.61 const size_t large_page = large_page_size(); 5.62 if (large_page > small_page) { 5.63 const size_t unaligned_region = large_page + 17; 5.64 - size_t page = os::page_size_for_region(unaligned_region, 1); 5.65 + size_t page = os::page_size_for_region_aligned(unaligned_region, 1); 5.66 assert_eq(page, small_page); 5.67 5.68 const size_t num_pages = 5; 5.69 const size_t aligned_region = large_page * num_pages; 5.70 - page = os::page_size_for_region(aligned_region, num_pages); 5.71 + page = os::page_size_for_region_aligned(aligned_region, num_pages); 5.72 assert_eq(page, large_page); 5.73 } 5.74 } 5.75 } 5.76 5.77 + static void test_page_size_for_region_unaligned() { 5.78 + if (UseLargePages) { 5.79 + // Given exact page size, should return that page size. 5.80 + for (size_t i = 0; os::_page_sizes[i] != 0; i++) { 5.81 + size_t expected = os::_page_sizes[i]; 5.82 + size_t actual = os::page_size_for_region_unaligned(expected, 1); 5.83 + assert_eq(expected, actual); 5.84 + } 5.85 + 5.86 + // Given slightly larger size than a page size, return the page size. 5.87 + for (size_t i = 0; os::_page_sizes[i] != 0; i++) { 5.88 + size_t expected = os::_page_sizes[i]; 5.89 + size_t actual = os::page_size_for_region_unaligned(expected + 17, 1); 5.90 + assert_eq(expected, actual); 5.91 + } 5.92 + 5.93 + // Given a slightly smaller size than a page size, 5.94 + // return the next smaller page size. 5.95 + if (os::_page_sizes[1] > os::_page_sizes[0]) { 5.96 + size_t expected = os::_page_sizes[0]; 5.97 + size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1); 5.98 + assert_eq(actual, expected); 5.99 + } 5.100 + 5.101 + // Return small page size for values less than a small page. 5.102 + size_t small_page = small_page_size(); 5.103 + size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1); 5.104 + assert_eq(small_page, actual); 5.105 + } 5.106 + } 5.107 + 5.108 public: 5.109 static void run_tests() { 5.110 - test_page_size_for_region(); 5.111 + test_page_size_for_region_aligned(); 5.112 test_page_size_for_region_alignment(); 5.113 + test_page_size_for_region_unaligned(); 5.114 } 5.115 }; 5.116
6.1 --- a/src/share/vm/runtime/os.hpp Wed Nov 26 10:32:21 2014 -0800 6.2 +++ b/src/share/vm/runtime/os.hpp Fri Jan 16 10:29:12 2015 +0100 6.3 @@ -149,6 +149,7 @@ 6.4 static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint); 6.5 static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint); 6.6 6.7 + static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); 6.8 6.9 public: 6.10 static void init(void); // Called before command line parsing 6.11 @@ -267,8 +268,13 @@ 6.12 6.13 // Returns the page size to use for a region of memory. 6.14 // region_size / min_pages will always be greater than or equal to the 6.15 - // returned value. 6.16 - static size_t page_size_for_region(size_t region_size, size_t min_pages); 6.17 + // returned value. The returned value will divide region_size. 6.18 + static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages); 6.19 + 6.20 + // Returns the page size to use for a region of memory. 6.21 + // region_size / min_pages will always be greater than or equal to the 6.22 + // returned value. The returned value might not divide region_size. 6.23 + static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages); 6.24 6.25 // Return the largest page size that can be used 6.26 static size_t max_page_size() {
7.1 --- a/src/share/vm/runtime/virtualspace.cpp Wed Nov 26 10:32:21 2014 -0800 7.2 +++ b/src/share/vm/runtime/virtualspace.cpp Fri Jan 16 10:29:12 2015 +0100 7.3 @@ -53,7 +53,8 @@ 7.4 } 7.5 7.6 ReservedSpace::ReservedSpace(size_t size) { 7.7 - size_t page_size = os::page_size_for_region(size, 1); 7.8 + // Want to use large pages where possible and pad with small pages. 7.9 + size_t page_size = os::page_size_for_region_unaligned(size, 1); 7.10 bool large_pages = page_size != (size_t)os::vm_page_size(); 7.11 // Don't force the alignment to be large page aligned, 7.12 // since that will waste memory. 7.13 @@ -372,7 +373,7 @@ 7.14 7.15 7.16 bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) { 7.17 - const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1); 7.18 + const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1); 7.19 return initialize_with_granularity(rs, committed_size, max_commit_granularity); 7.20 } 7.21 7.22 @@ -995,7 +996,7 @@ 7.23 case Disable: 7.24 return vs.initialize_with_granularity(rs, 0, os::vm_page_size()); 7.25 case Commit: 7.26 - return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1)); 7.27 + return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1)); 7.28 } 7.29 } 7.30