New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8272773: Configurable card table card size #5838
Changes from 4 commits
c9d5203
8306221
9247350
c9c8db8
43fa93e
9d02c66
475de50
1f0612a
125a0af
0d1e15d
6d7b084
a3551a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1661,7 +1661,7 @@ jint G1CollectedHeap::initialize() { | ||
|
||
// The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not | ||
// start within the first card. | ||
guarantee(heap_rs.base() >= (char*)G1CardTable::card_size, "Java heap must not start within the first card."); | ||
guarantee(heap_rs.base() >= (char*)(uintptr_t)(G1CardTable::card_size), "Java heap must not start within the first card."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about |
||
G1FromCardCache::initialize(max_reserved_regions()); | ||
// Also create a G1 rem set. | ||
_rem_set = new G1RemSet(this, _card_table, _hot_card_cache); | ||
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -52,11 +52,16 @@ class ObjectStartArray : public CHeapObj<mtGC> { | ||||||||||
clean_block = -1 | ||||||||||
}; | ||||||||||
|
||||||||||
enum BlockSizeConstants { | ||||||||||
block_shift = 9, | ||||||||||
block_size = 1 << block_shift, | ||||||||||
block_size_in_words = block_size / sizeof(HeapWord) | ||||||||||
}; | ||||||||||
static uint block_shift; | ||||||||||
static uint block_size; | ||||||||||
static uint block_size_in_words; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the naming guideline for static members is the same as for regular class members, i.e. use an underscore in front. Maybe wait on changing this for another person to comment on (I did not look up the style guide). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I've kept the names of all the pre-existing constants (which are now variables) same as before. Otherwise we have to change all the references also. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's see what the second reviewer thinks. Otherwise this can be done separately as it might hide the interesting part of this change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a review (yet), just a response to these questions. Public data members are very rare in HotSpot code. There are a few POD/standard layout classes (examples include G1BufferNodeList and OopStorage::BasicParState::IterationData), but otherwise accessor functions are preferred. The style-guide says The style-guide says this: Of course, there are probably counter-examples to both of these lurking in the code base. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer if this introduction of getters were moved to an extra CR, but I'm good to do that now as well; not so much a problem with the |
||||||||||
|
||||||||||
// This maximum is derived from that we need an extra bit for possible | ||||||||||
// offsets in the byte for backskip values (this is a hard limit) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(We could make this maximum dependent on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it is interesting to make this size depend on current Maybe it is interesting for you to try out even larger card sizes though (e.g. an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. I'll explore this and share the results. |
||||||||||
static const uint MaxBlockSize = 1024; | ||||||||||
|
||||||||||
// Initialize block size based on card size | ||||||||||
static void initialize_block_size(uint card_shift); | ||||||||||
|
||||||||||
protected: | ||||||||||
|
||||||||||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -26,13 +26,48 @@ | ||
#include "gc/shared/cardTable.hpp" | ||
#include "gc/shared/collectedHeap.hpp" | ||
#include "gc/shared/space.inline.hpp" | ||
#include "gc/shared/gcLogPrecious.hpp" | ||
#include "gc/parallel/objectStartArray.hpp" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This include is in the wrong order and should probably be guarded by |
||
#include "logging/log.hpp" | ||
#include "memory/virtualspace.hpp" | ||
#include "runtime/java.hpp" | ||
#include "runtime/os.hpp" | ||
#include "runtime/globals_extension.hpp" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we typically include the globals include that contains the flag - this should probably be |
||
#include "services/memTracker.hpp" | ||
#include "utilities/align.hpp" | ||
|
||
uint CardTable::card_shift = 0; | ||
uint CardTable::card_size = 0; | ||
uint CardTable::card_size_in_words = 0; | ||
|
||
void CardTable::initialize_card_size(uint min_card_size) { | ||
assert(UseG1GC || UseParallelGC || UseSerialGC, | ||
"Initialize card size should only be called by card based collectors."); | ||
|
||
// Card size is the max. of minimum permissible value and GCCardSizeInBytes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outdated comment. Remove. |
||
card_size = MAX2(min_card_size, GCCardSizeInBytes); | ||
card_shift = log2i_exact(card_size); | ||
card_size_in_words = card_size / sizeof(HeapWord); | ||
|
||
// Set blockOffsetTable size based on card table entry size | ||
BOTConstants::initialize_bot_size(card_shift); | ||
|
||
#if INCLUDE_PARALLELGC | ||
// Set ObjectStartArray block size based on card table entry size | ||
ObjectStartArray::initialize_block_size(card_shift); | ||
#endif | ||
|
||
if (GCCardSizeInBytes != card_size) { | ||
FLAG_SET_ERGO(GCCardSizeInBytes, card_size); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would also be unnecessary with a constraint function that limits the values of the option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FLAG_SET_ERGO is needed for G1 GC. In case of G1, min card size is determined by the region size. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leave this question out for now: I am not sure it makes sense to allow a card size of 256; however the common reaction when specifying incompatible command line options would be to bail out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That same question will come up if we allow 64m regions later, but the step from 64->32m may not be that big. Another option would be to go away from the 1:1 mapping of cards in the remembered set and cards in the card table. This could probably be fixed, but is a completely different issue of course. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this current implementation, with G1 GC, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the code, but the problems are elsewhere:
|
||
log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, card_size); | ||
} | ||
|
||
void CardTable::initialize_card_size() { | ||
initialize_card_size(CardSizeMin); | ||
} | ||
|
||
size_t CardTable::compute_byte_map_size() { | ||
assert(_guard_index == cards_required(_whole_heap.word_size()) - 1, | ||
"uninitialized, check declaration order"); | ||
@@ -41,6 +76,7 @@ size_t CardTable::compute_byte_map_size() { | ||
return align_up(_guard_index + 1, MAX2(_page_size, granularity)); | ||
} | ||
|
||
|
||
CardTable::CardTable(MemRegion whole_heap) : | ||
_whole_heap(whole_heap), | ||
_guard_index(0), | ||
@@ -56,8 +92,6 @@ CardTable::CardTable(MemRegion whole_heap) : | ||
{ | ||
assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary"); | ||
assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary"); | ||
|
||
assert(card_size <= 512, "card_size must be less than 512"); // why? | ||
} | ||
|
||
CardTable::~CardTable() { | ||
@@ -428,7 +462,8 @@ MemRegion CardTable::dirty_card_range_after_reset(MemRegion mr, | ||
} | ||
|
||
uintx CardTable::ct_max_alignment_constraint() { | ||
return card_size * os::vm_page_size(); | ||
// CardTable max alignment is computed with card_size_max | ||
return CardSizeMax * os::vm_page_size(); | ||
} | ||
|
||
void CardTable::verify_guard() { | ||
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -692,9 +692,13 @@ | ||||||
product(uintx, GCDrainStackTargetSize, 64, \ | ||||||
"Number of entries we will try to leave on the stack " \ | ||||||
"during parallel gc") \ | ||||||
range(0, max_juint) | ||||||
|
||||||
// end of GC_FLAGS | ||||||
range(0, max_juint) \ | ||||||
\ | ||||||
product(uint, GCCardSizeInBytes, 512, \ | ||||||
"Card table entry size (in bytes) for card based collectors") \ | ||||||
range(512, 1024) \ | ||||||
constraint(GCCardSizeInBytesConstraintFunc, AfterErgo) \ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Before |
||||||
// end of GC_FLAGS | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See e.g. |
||||||
|
||||||
DECLARE_FLAGS(GC_FLAGS) | ||||||
|
||||||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -424,3 +424,17 @@ JVMFlag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) { | ||
} | ||
} | ||
|
||
JVMFlag::Error GCCardSizeInBytesConstraintFunc(uint value, bool verbose) { | ||
if(!(UseG1GC || UseParallelGC || UseSerialGC)) | ||
return JVMFlag::SUCCESS; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this check - if we are doing the constraint check at parse time, the |
||
if (!is_power_of_2(value)) { | ||
JVMFlag::printError(verbose, | ||
"GCCardSizeInBytes (" UINT32_FORMAT ") must be " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use |
||
"a power of 2\n", | ||
value); | ||
return JVMFlag::VIOLATES_CONSTRAINT; | ||
} else { | ||
return JVMFlag::SUCCESS; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tschatzl Do we need this code once JDK-8275056 (Virtualize G1CardSet containers over heap region) gets integrated? From my understanding, this won't be a restriction from heap region point of view. Do I need to remove this and the changes in
g1CardTable.cpp
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. The change you will need will be very similar to 70dcca6 (slightly modified because of review comments); but please wait until it is in. No hurry though, we'll need to complete the CSR before we can integrate anyway.
Thomas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, got it.