Skip to content

Commit ddd9631

Browse files
committed
8294677: chunklevel::MAX_CHUNK_WORD_SIZE too small for some applications
Reviewed-by: phh, xliu Backport-of: 2292ce137c16accf0622600d5a096403b8a8058d
1 parent 0ed3689 commit ddd9631

File tree

10 files changed

+94
-66
lines changed

10 files changed

+94
-66
lines changed

src/hotspot/share/memory/metaspace/chunklevel.hpp

+25-29
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,13 @@ namespace metaspace {
4646
// From there on it goes:
4747
//
4848
// size level
49-
// 4MB 0
50-
// 2MB 1
51-
// 1MB 2
52-
// 512K 3
53-
// 256K 4
54-
// 128K 5
55-
// 64K 6
56-
// 32K 7
57-
// 16K 8
58-
// 8K 9
59-
// 4K 10
60-
// 2K 11
61-
// 1K 12
49+
// 16MB 0
50+
// 8MB 1
51+
// 4MB 2
52+
// ...
53+
// 4K 12
54+
// 2K 13
55+
// 1K 14
6256

6357
// Metachunk level (must be signed)
6458
typedef signed char chunklevel_t;
@@ -67,8 +61,8 @@ typedef signed char chunklevel_t;
6761

6862
namespace chunklevel {
6963

70-
static const size_t MAX_CHUNK_BYTE_SIZE = 4 * M;
71-
static const int NUM_CHUNK_LEVELS = 13;
64+
static const size_t MAX_CHUNK_BYTE_SIZE = 16 * M;
65+
static const int NUM_CHUNK_LEVELS = 15;
7266
static const size_t MIN_CHUNK_BYTE_SIZE = (MAX_CHUNK_BYTE_SIZE >> ((size_t)NUM_CHUNK_LEVELS - 1));
7367

7468
static const size_t MIN_CHUNK_WORD_SIZE = MIN_CHUNK_BYTE_SIZE / sizeof(MetaWord);
@@ -101,22 +95,24 @@ inline size_t word_size_for_level(chunklevel_t level) {
10195
chunklevel_t level_fitting_word_size(size_t word_size);
10296

10397
// Shorthands to refer to exact sizes
104-
static const chunklevel_t CHUNK_LEVEL_4M = ROOT_CHUNK_LEVEL;
105-
static const chunklevel_t CHUNK_LEVEL_2M = (ROOT_CHUNK_LEVEL + 1);
106-
static const chunklevel_t CHUNK_LEVEL_1M = (ROOT_CHUNK_LEVEL + 2);
107-
static const chunklevel_t CHUNK_LEVEL_512K = (ROOT_CHUNK_LEVEL + 3);
108-
static const chunklevel_t CHUNK_LEVEL_256K = (ROOT_CHUNK_LEVEL + 4);
109-
static const chunklevel_t CHUNK_LEVEL_128K = (ROOT_CHUNK_LEVEL + 5);
110-
static const chunklevel_t CHUNK_LEVEL_64K = (ROOT_CHUNK_LEVEL + 6);
111-
static const chunklevel_t CHUNK_LEVEL_32K = (ROOT_CHUNK_LEVEL + 7);
112-
static const chunklevel_t CHUNK_LEVEL_16K = (ROOT_CHUNK_LEVEL + 8);
113-
static const chunklevel_t CHUNK_LEVEL_8K = (ROOT_CHUNK_LEVEL + 9);
114-
static const chunklevel_t CHUNK_LEVEL_4K = (ROOT_CHUNK_LEVEL + 10);
115-
static const chunklevel_t CHUNK_LEVEL_2K = (ROOT_CHUNK_LEVEL + 11);
116-
static const chunklevel_t CHUNK_LEVEL_1K = (ROOT_CHUNK_LEVEL + 12);
98+
static const chunklevel_t CHUNK_LEVEL_16M = ROOT_CHUNK_LEVEL;
99+
static const chunklevel_t CHUNK_LEVEL_8M = (ROOT_CHUNK_LEVEL + 1);
100+
static const chunklevel_t CHUNK_LEVEL_4M = (ROOT_CHUNK_LEVEL + 2);
101+
static const chunklevel_t CHUNK_LEVEL_2M = (ROOT_CHUNK_LEVEL + 3);
102+
static const chunklevel_t CHUNK_LEVEL_1M = (ROOT_CHUNK_LEVEL + 4);
103+
static const chunklevel_t CHUNK_LEVEL_512K = (ROOT_CHUNK_LEVEL + 5);
104+
static const chunklevel_t CHUNK_LEVEL_256K = (ROOT_CHUNK_LEVEL + 6);
105+
static const chunklevel_t CHUNK_LEVEL_128K = (ROOT_CHUNK_LEVEL + 7);
106+
static const chunklevel_t CHUNK_LEVEL_64K = (ROOT_CHUNK_LEVEL + 8);
107+
static const chunklevel_t CHUNK_LEVEL_32K = (ROOT_CHUNK_LEVEL + 9);
108+
static const chunklevel_t CHUNK_LEVEL_16K = (ROOT_CHUNK_LEVEL + 10);
109+
static const chunklevel_t CHUNK_LEVEL_8K = (ROOT_CHUNK_LEVEL + 11);
110+
static const chunklevel_t CHUNK_LEVEL_4K = (ROOT_CHUNK_LEVEL + 12);
111+
static const chunklevel_t CHUNK_LEVEL_2K = (ROOT_CHUNK_LEVEL + 13);
112+
static const chunklevel_t CHUNK_LEVEL_1K = (ROOT_CHUNK_LEVEL + 14);
117113

118114
STATIC_ASSERT(CHUNK_LEVEL_1K == HIGHEST_CHUNK_LEVEL);
119-
STATIC_ASSERT(CHUNK_LEVEL_4M == LOWEST_CHUNK_LEVEL);
115+
STATIC_ASSERT(CHUNK_LEVEL_16M == LOWEST_CHUNK_LEVEL);
120116
STATIC_ASSERT(ROOT_CHUNK_LEVEL == LOWEST_CHUNK_LEVEL);
121117

122118
/////////////////////////////////////////////////////////

src/hotspot/share/memory/metaspace/metaspaceSettings.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class Settings : public AllStatic {
4747
// Note that this only affects the non-class metaspace. Class space ignores this size (it is one
4848
// single large mapping).
4949
static const size_t _virtual_space_node_default_word_size =
50-
chunklevel::MAX_CHUNK_WORD_SIZE * NOT_LP64(2) LP64_ONLY(16); // 8MB (32-bit) / 64MB (64-bit)
50+
chunklevel::MAX_CHUNK_WORD_SIZE * NOT_LP64(1) LP64_ONLY(4); // 16MB (32-bit) / 64MB (64-bit)
5151

5252
// Alignment of the base address of a virtual space node
5353
static const size_t _virtual_space_node_reserve_alignment_words = chunklevel::MAX_CHUNK_WORD_SIZE;

test/hotspot/gtest/metaspace/test_chunkManager_stress.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class ChunkManagerRandomChunkAllocTest {
190190

191191
// adjust test if we change levels
192192
STATIC_ASSERT(HIGHEST_CHUNK_LEVEL == CHUNK_LEVEL_1K);
193-
STATIC_ASSERT(LOWEST_CHUNK_LEVEL == CHUNK_LEVEL_4M);
193+
STATIC_ASSERT(LOWEST_CHUNK_LEVEL == CHUNK_LEVEL_16M);
194194

195195
void one_test() {
196196

test/hotspot/gtest/metaspace/test_metachunk.cpp

+40-13
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,51 @@ TEST_VM(metaspace, get_chunk) {
6262
// Test ChunkManager::get_chunk, but with a commit limit.
6363
TEST_VM(metaspace, get_chunk_with_commit_limit) {
6464

65-
const size_t commit_limit_words = 1 * M;
66-
ChunkGtestContext context(commit_limit_words);
67-
Metachunk* c = NULL;
65+
// A commit limit that is smaller than the largest possible chunk size.
6866

69-
for (chunklevel_t pref_lvl = LOWEST_CHUNK_LEVEL; pref_lvl <= HIGHEST_CHUNK_LEVEL; pref_lvl++) {
67+
// Here we test different combinations of commit limit, preferred and highest chunk level, and min_committed_size.
7068

71-
for (chunklevel_t max_lvl = pref_lvl; max_lvl <= HIGHEST_CHUNK_LEVEL; max_lvl++) {
69+
for (size_t commit_limit_words = Settings::commit_granule_words();
70+
commit_limit_words < MAX_CHUNK_WORD_SIZE * 2; commit_limit_words *= 2) {
7271

73-
for (size_t min_committed_words = Settings::commit_granule_words();
74-
min_committed_words <= word_size_for_level(max_lvl); min_committed_words *= 2) {
72+
ChunkGtestContext context(commit_limit_words);
73+
Metachunk* c = NULL;
7574

76-
if (min_committed_words <= commit_limit_words) {
77-
context.alloc_chunk_expect_success(&c, pref_lvl, max_lvl, min_committed_words);
78-
context.return_chunk(c);
79-
} else {
80-
context.alloc_chunk_expect_failure(pref_lvl, max_lvl, min_committed_words);
75+
for (chunklevel_t pref_lvl = LOWEST_CHUNK_LEVEL; pref_lvl <= HIGHEST_CHUNK_LEVEL; pref_lvl++) {
76+
77+
for (chunklevel_t max_lvl = pref_lvl; max_lvl <= HIGHEST_CHUNK_LEVEL; max_lvl++) {
78+
79+
for (size_t min_committed_words = Settings::commit_granule_words();
80+
min_committed_words <= word_size_for_level(max_lvl); min_committed_words *= 2) {
81+
82+
// When should commit work? As long as min_committed_words is smaller than commit_limit_words.
83+
bool commit_should_work = min_committed_words <= commit_limit_words;
84+
85+
// Exception: MetaspaceReclaimPolicy=none. Here, chunks are fully committed from the get go and
86+
// min_committed_words is effectively ignored. So commit would fail if the chunk is larger than
87+
// the commit limit. Unfortunately, the chunk size is difficult to predict (it will be between
88+
// [pref_lvl, max_lvl]. To make matters simple, we skip the test if we don't know the level for
89+
// sure.
90+
if (Settings::new_chunks_are_fully_committed()) {
91+
if (pref_lvl == max_lvl) {
92+
commit_should_work = word_size_for_level(max_lvl) <= commit_limit_words;
93+
} else {
94+
continue;
95+
}
96+
}
97+
98+
// printf("commit_limit: " SIZE_FORMAT ", min_committed_words: " SIZE_FORMAT
99+
// ", max chunk level: " CHKLVL_FORMAT ", preferred chunk level: " CHKLVL_FORMAT ", should work: %d\n",
100+
// commit_limit_words, min_committed_words, max_lvl, pref_lvl, commit_should_work);
101+
// fflush(stdout);
102+
103+
if (commit_should_work) {
104+
context.alloc_chunk_expect_success(&c, pref_lvl, max_lvl, min_committed_words);
105+
context.return_chunk(c);
106+
} else {
107+
context.alloc_chunk_expect_failure(pref_lvl, max_lvl, min_committed_words);
108+
}
81109
}
82-
83110
}
84111
}
85112
}

test/hotspot/gtest/metaspace/test_metaspace_misc.cpp

+16-10
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,28 @@ TEST_VM(metaspace, misc_sizes) {
4646
ASSERT_EQ(Settings::commit_granule_bytes(), Metaspace::commit_alignment());
4747
ASSERT_TRUE(is_aligned(Settings::virtual_space_node_default_word_size(),
4848
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE));
49-
ASSERT_EQ(Settings::virtual_space_node_default_word_size(),
50-
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * NOT_LP64(2) LP64_ONLY(16));
49+
ASSERT_EQ(Settings::virtual_space_node_default_word_size() * BytesPerWord, NOT_LP64(16) LP64_ONLY(64) * M);
5150
ASSERT_EQ(Settings::virtual_space_node_reserve_alignment_words(),
5251
Metaspace::reserve_alignment_words());
5352

5453
}
5554

5655
TEST_VM(metaspace, misc_max_alloc_size) {
57-
58-
// Make sure we can allocate what we promise to allocate
59-
const size_t sz = Metaspace::max_allocation_word_size();
60-
ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
61-
MetaWord* p = cld->metaspace_non_null()->allocate(sz, Metaspace::NonClassType);
62-
ASSERT_NOT_NULL(p);
63-
cld->metaspace_non_null()->deallocate(p, sz, false);
64-
56+
// Make sure we can allocate what we promise to allocate...
57+
for (int i = 0; i < 2; i ++) {
58+
const bool in_class_space = (i == 0);
59+
const Metaspace::MetadataType mdType = in_class_space ? Metaspace::ClassType : Metaspace::NonClassType;
60+
const size_t sz = Metaspace::max_allocation_word_size();
61+
ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data();
62+
MetaWord* p = cld->metaspace_non_null()->allocate(sz, mdType);
63+
if (p == nullptr) {
64+
// Have we run into the GC threshold?
65+
p = cld->metaspace_non_null()->expand_and_allocate(sz, mdType);
66+
ASSERT_NOT_NULL(p);
67+
}
68+
// And also, successfully deallocate it.
69+
cld->metaspace_non_null()->deallocate(p, sz, in_class_space);
70+
}
6571
}
6672

6773
TEST_VM(metaspace, chunklevel_utils) {

test/hotspot/gtest/metaspace/test_virtualspacenode.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ TEST_VM(metaspace, virtual_space_node_test_basics) {
493493

494494
MutexLocker fcl(Metaspace_lock, Mutex::_no_safepoint_check_flag);
495495

496-
const size_t word_size = metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 10;
496+
const size_t word_size = metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 3;
497497

498498
SizeCounter scomm;
499499
SizeCounter sres;
@@ -580,13 +580,13 @@ TEST_VM(metaspace, virtual_space_node_test_5) {
580580
TEST_VM(metaspace, virtual_space_node_test_7) {
581581
// Test large allocation and freeing.
582582
{
583-
VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 100,
584-
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 100);
583+
VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 25,
584+
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 25);
585585
test.test_exhaust_node();
586586
}
587587
{
588-
VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 100,
589-
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 100);
588+
VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 25,
589+
metaspace::chunklevel::MAX_CHUNK_WORD_SIZE * 25);
590590
test.test_exhaust_node();
591591
}
592592

test/hotspot/jtreg/runtime/CompressedOops/CompressedClassSpaceSize.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ public static void main(String[] args) throws Exception {
6464

6565

6666
// Make sure the minimum size is set correctly and printed
67-
// (Note: ccs size shall be rounded up to the minimum size of 4m since metaspace reservations
68-
// are done in a 4m granularity. Note that this is **reserved** size and does not affect rss.
67+
// (Note: ccs size are rounded up to the next larger root chunk boundary (16m).
68+
// Note that this is **reserved** size and does not affect rss.
6969
pb = ProcessTools.createJavaProcessBuilder("-XX:+UnlockDiagnosticVMOptions",
7070
"-XX:CompressedClassSpaceSize=1m",
7171
"-Xlog:gc+metaspace=trace",
7272
"-version");
7373
output = new OutputAnalyzer(pb.start());
74-
output.shouldMatch("Compressed class space.*4194304")
74+
output.shouldMatch("Compressed class space.*16777216")
7575
.shouldHaveExitValue(0);
7676

7777

test/hotspot/jtreg/runtime/Metaspace/elastic/Settings.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ final public boolean doesReclaim() {
3434
return reclaimPolicy.equals("balanced") || reclaimPolicy.equals("aggessive");
3535
}
3636

37-
final static long rootChunkWordSize = 512 * 1024;
37+
final static long rootChunkWordSize = 2048 * 1024;
3838

3939
static Settings theSettings;
4040

test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public static void main(String[] args) throws Exception {
175175

176176
// Note: reserve limit must be a multiple of Metaspace::reserve_alignment_words()
177177
// (512K on 64bit, 1M on 32bit)
178-
long reserveLimit = (i == 2) ? 1024 * 1024 : 0;
178+
long reserveLimit = (i == 2) ? Settings.rootChunkWordSize * 2 : 0;
179179

180180
System.out.println("#### Test: ");
181181
System.out.println("#### testAllocationCeiling: " + testAllocationCeiling);

test/hotspot/jtreg/runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ public static void main(String[] args) throws Exception {
174174
long commitLimit = (i == 1) ? 1024 * 256 : 0;
175175

176176
// Note: reserve limit must be a multiple of Metaspace::reserve_alignment_words()
177-
// (512K on 64bit, 1M on 32bit)
178-
long reserveLimit = (i == 2) ? 1024 * 1024 : 0;
177+
long reserveLimit = (i == 2) ? Settings.rootChunkWordSize * 2 : 0;
179178

180179
System.out.println("#### Test: ");
181180
System.out.println("#### testAllocationCeiling: " + testAllocationCeiling);

0 commit comments

Comments
 (0)