加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
NUMA-Aware-Implementation-humongous-region.patch 41.85 KB
一键复制 编辑 原始数据 按行查看 历史
jdkboy 提交于 2020-08-31 10:36 . Add several enhancement patches
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956
diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp
index 0fcfe4e96..a0ecfd393 100644
--- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp
+++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp
@@ -34,6 +34,7 @@
// Forward declarations
class G1BlockOffsetTable;
class G1ContiguousSpace;
+class G1RegionToSpaceMapper;
// This implementation of "G1BlockOffsetTable" divides the covered region
// into "N"-word subregions (where "N" = 2^"LogN". An array with an entry
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index 3bb5b56e8..a987377ae 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -343,7 +343,8 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
} else {
// Policy: Try only empty regions (i.e. already committed first). Maybe we
// are lucky enough to find some.
- first = _hrm.find_contiguous_only_empty(obj_regions);
+ uint node_index = _numa->is_humongous_region_enabled() ? _numa->index_of_current_thread() : G1NUMA::AnyNodeIndex;
+ first = _hrm.find_contiguous_only_empty(obj_regions, node_index);
if (first != G1_NO_HRM_INDEX) {
_hrm.allocate_free_regions_starting_at(first, obj_regions);
}
@@ -353,14 +354,15 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
// Policy: We could not find enough regions for the humongous object in the
// free list. Look through the heap to find a mix of free and uncommitted regions.
// If so, try expansion.
- first = _hrm.find_contiguous_empty_or_unavailable(obj_regions);
+ uint node_index = _numa->is_humongous_region_enabled() ? _numa->index_of_current_thread() : G1NUMA::AnyNodeIndex;
+ first = _hrm.find_contiguous_empty_or_unavailable(obj_regions, node_index);
if (first != G1_NO_HRM_INDEX) {
// We found something. Make sure these regions are committed, i.e. expand
// the heap. Alternatively we could do a defragmentation GC.
log_debug(gc, ergo, heap)("Attempt heap expansion (humongous allocation request failed). Allocation request: " SIZE_FORMAT "B",
word_size * HeapWordSize);
- _hrm.expand_at(first, obj_regions, workers());
+ _hrm.expand_at(first, obj_regions, workers(), node_index);
g1_policy()->record_new_heap_size(num_regions());
#ifdef ASSERT
@@ -4823,7 +4825,7 @@ public:
HeapRegionSet* old_set, HeapRegionManager* hrm) :
_free_list_only(free_list_only),
_old_set(old_set), _hrm(hrm), _total_used(0) {
- assert(_hrm.num_free_regions() == 0, "pre-condition");
+ assert(_hrm->num_free_regions() == 0, "pre-condition");
if (!free_list_only) {
assert(_old_set->is_empty(), "pre-condition");
}
diff --git a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp
index 71342b4d2..22fd0bd95 100644
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp
@@ -777,7 +777,7 @@ class G1CheckCSetFastTableClosure : public HeapRegionClosure {
bool G1HeapVerifier::check_cset_fast_test() {
G1CheckCSetFastTableClosure cl;
- _g1h->_hrm->iterate(&cl);
+ _g1h->_hrm.iterate(&cl);
return !cl.failures();
}
#endif // PRODUCT
diff --git a/src/hotspot/share/gc/g1/g1NUMA.cpp b/src/hotspot/share/gc/g1/g1NUMA.cpp
index 95d9d8c15..fada40f13 100644
--- a/src/hotspot/share/gc/g1/g1NUMA.cpp
+++ b/src/hotspot/share/gc/g1/g1NUMA.cpp
@@ -42,6 +42,8 @@ size_t G1NUMA::page_size() const {
bool G1NUMA::is_enabled() const { return num_active_nodes() > 1; }
+bool G1NUMA::is_humongous_region_enabled() const { return UseNUMAHumongous && num_active_nodes() > 1; }
+
G1NUMA* G1NUMA::create() {
guarantee(_inst == NULL, "Should be called once.");
_inst = new G1NUMA();
@@ -203,7 +205,7 @@ uint G1NUMA::index_for_region(HeapRegion* hr) const {
// * Page #: |-----0----||-----1----||-----2----||-----3----||-----4----||-----5----||-----6----||-----7----|
// * HeapRegion #: |-#0-||-#1-||-#2-||-#3-||-#4-||-#5-||-#6-||-#7-||-#8-||-#9-||#10-||#11-||#12-||#13-||#14-||#15-|
// * NUMA node #: |----#0----||----#1----||----#2----||----#3----||----#0----||----#1----||----#2----||----#3----|
-void G1NUMA::request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index) {
+void G1NUMA::request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index, uint node) {
if (!is_enabled()) {
return;
}
@@ -212,7 +214,7 @@ void G1NUMA::request_memory_on_node(void* aligned_address, size_t size_in_bytes,
return;
}
- uint node_index = preferred_node_index_for_index(region_index);
+ uint node_index = node == G1NUMA::AnyNodeIndex ? preferred_node_index_for_index(region_index) : node;
assert(is_aligned(aligned_address, page_size()), "Given address (" PTR_FORMAT ") should be aligned.", p2i(aligned_address));
assert(is_aligned(size_in_bytes, page_size()), "Given size (" SIZE_FORMAT ") should be aligned.", size_in_bytes);
diff --git a/src/hotspot/share/gc/g1/g1NUMA.hpp b/src/hotspot/share/gc/g1/g1NUMA.hpp
index 2bfad205b..56889057f 100644
--- a/src/hotspot/share/gc/g1/g1NUMA.hpp
+++ b/src/hotspot/share/gc/g1/g1NUMA.hpp
@@ -89,6 +89,8 @@ public:
bool is_enabled() const;
+ bool is_humongous_region_enabled() const;
+
int numa_id(int index) const;
// Returns memory node ids
@@ -113,7 +115,7 @@ public:
uint index_for_region(HeapRegion* hr) const;
// Requests the given memory area to be located at the given node index.
- void request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index);
+ void request_memory_on_node(void* aligned_address, size_t size_in_bytes, uint region_index, uint node = AnyNodeIndex);
// Returns maximum search depth which is used to limit heap region search iterations.
// The number of active nodes, page size and heap region size are considered.
diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp
index dba2d1734..67595e05b 100644
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp
@@ -69,7 +69,7 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
guarantee(alloc_granularity >= page_size, "allocation granularity smaller than commit granularity");
}
- virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang) {
+ virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang, uint node) {
const size_t start_page = (size_t)start_idx * _pages_per_region;
const size_t size_in_pages = num_regions * _pages_per_region;
bool zero_filled = _storage.commit(start_page, size_in_pages);
@@ -77,7 +77,7 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
for (uint region_index = start_idx; region_index < start_idx + num_regions; region_index++ ) {
void* address = _storage.page_start(region_index * _pages_per_region);
size_t size_in_bytes = _storage.page_size() * _pages_per_region;
- G1NUMA::numa()->request_memory_on_node(address, size_in_bytes, region_index);
+ G1NUMA::numa()->request_memory_on_node(address, size_in_bytes, region_index, node);
}
}
if (AlwaysPreTouch) {
@@ -125,7 +125,7 @@ class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
_refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + align_up(rs.size(), page_size)), page_size);
}
- virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang) {
+ virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang, uint node) {
size_t const NoPage = ~(size_t)0;
size_t first_committed = NoPage;
diff --git a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp
index 30f7bf54c..6b396c8e3 100644
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_G1_G1REGIONTOSPACEMAPPER_HPP
#define SHARE_VM_GC_G1_G1REGIONTOSPACEMAPPER_HPP
+#include "gc/g1/g1NUMA.hpp"
#include "gc/g1/g1PageBasedVirtualSpace.hpp"
#include "memory/allocation.hpp"
#include "utilities/debug.hpp"
@@ -72,7 +73,7 @@ class G1RegionToSpaceMapper : public CHeapObj<mtGC> {
return _commit_map.at(idx);
}
- virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkGang* pretouch_workers = NULL) = 0;
+ virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkGang* pretouch_workers = NULL, uint node = G1NUMA::AnyNodeIndex) = 0;
virtual void uncommit_regions(uint start_idx, size_t num_regions = 1) = 0;
// Creates an appropriate G1RegionToSpaceMapper for the given parameters.
diff --git a/src/hotspot/share/gc/g1/heapRegionManager.cpp b/src/hotspot/share/gc/g1/heapRegionManager.cpp
index 10a0d58a5..9dc86eb21 100644
--- a/src/hotspot/share/gc/g1/heapRegionManager.cpp
+++ b/src/hotspot/share/gc/g1/heapRegionManager.cpp
@@ -37,6 +37,11 @@
#include "runtime/orderAccess.hpp"
#include "utilities/bitMap.inline.hpp"
+// Avoid allocating too many humongous regions in the same node
+// at most (humongous regions already allocated)/ BALANCE_FACTOR_FOR_HUMONGOUS
+// if this threshold is exceeded, fallback to the original scheme
+const int BALANCE_FACTOR_FOR_HUMONGOUS = 2;
+
class MasterFreeRegionListChecker : public HeapRegionSetChecker {
public:
void check_mt_safety() {
@@ -134,23 +139,23 @@ HeapRegion* HeapRegionManager::new_heap_region(uint hrm_index) {
assert(reserved().contains(mr), "invariant");
return g1h->new_heap_region(hrm_index, mr);
}
-
-void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkGang* pretouch_gang) {
+
+void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkGang* pretouch_gang, uint node) {
guarantee(num_regions > 0, "Must commit more than zero regions");
guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions");
_num_committed += (uint)num_regions;
- _heap_mapper->commit_regions(index, num_regions, pretouch_gang);
+ _heap_mapper->commit_regions(index, num_regions, pretouch_gang, node);
// Also commit auxiliary data
- _prev_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang);
- _next_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang);
+ _prev_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang, node);
+ _next_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang, node);
- _bot_mapper->commit_regions(index, num_regions, pretouch_gang);
- _cardtable_mapper->commit_regions(index, num_regions, pretouch_gang);
+ _bot_mapper->commit_regions(index, num_regions, pretouch_gang, node);
+ _cardtable_mapper->commit_regions(index, num_regions, pretouch_gang, node);
- _card_counts_mapper->commit_regions(index, num_regions, pretouch_gang);
+ _card_counts_mapper->commit_regions(index, num_regions, pretouch_gang, node);
}
void HeapRegionManager::uncommit_regions(uint start, size_t num_regions) {
@@ -185,9 +190,22 @@ void HeapRegionManager::uncommit_regions(uint start, size_t num_regions) {
_card_counts_mapper->uncommit_regions(start, num_regions);
}
-void HeapRegionManager::make_regions_available(uint start, uint num_regions, WorkGang* pretouch_gang) {
+void HeapRegionManager::make_regions_available(uint start, uint num_regions, WorkGang* pretouch_gang, uint node) {
guarantee(num_regions > 0, "No point in calling this for zero regions");
- commit_regions(start, num_regions, pretouch_gang);
+ if (node != G1NUMA::AnyNodeIndex) {
+ G1NUMA* numa = G1NUMA::numa();
+ guarantee(numa->is_humongous_region_enabled(), "NUMA Humongous should be enabled in calling this");
+ guarantee(node < numa->num_active_nodes(), "node should be less than active nodes");
+ uint sum = 0;
+ for (uint i = 0; i < numa->num_active_nodes(); i++) {
+ sum += _humongous.count(i);
+ }
+ uint regionsOnThisNode = _humongous.count(node);
+ if (BALANCE_FACTOR_FOR_HUMONGOUS * regionsOnThisNode > sum + num_regions) {
+ node = G1NUMA::AnyNodeIndex;
+ }
+ }
+ commit_regions(start, num_regions, pretouch_gang, node);
for (uint i = start; i < start + num_regions; i++) {
if (_regions.get_by_index(i) == NULL) {
HeapRegion* new_hr = new_heap_region(i);
@@ -209,7 +227,10 @@ void HeapRegionManager::make_regions_available(uint start, uint num_regions, Wor
MemRegion mr(bottom, bottom + HeapRegion::GrainWords);
hr->initialize(mr);
- hr->set_node_index(G1NUMA::numa()->index_for_region(hr));
+ hr->set_node_index(node == G1NUMA::AnyNodeIndex ? G1NUMA::numa()->index_for_region(hr) : node);
+ if (node != G1NUMA::AnyNodeIndex) {
+ _humongous.add(hr);
+ }
insert_into_free_list(at(i));
}
}
@@ -236,7 +257,7 @@ uint HeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers)
return expand_at(0, num_regions, pretouch_workers);
}
-uint HeapRegionManager::expand_at(uint start, uint num_regions, WorkGang* pretouch_workers) {
+uint HeapRegionManager::expand_at(uint start, uint num_regions, WorkGang* pretouch_workers, uint node) {
if (num_regions == 0) {
return 0;
}
@@ -250,7 +271,7 @@ uint HeapRegionManager::expand_at(uint start, uint num_regions, WorkGang* pretou
while (expanded < num_regions &&
(num_last_found = find_unavailable_from_idx(cur, &idx_last_found)) > 0) {
uint to_expand = MIN2(num_regions - expanded, num_last_found);
- make_regions_available(idx_last_found, to_expand, pretouch_workers);
+ make_regions_available(idx_last_found, to_expand, pretouch_workers, node);
expanded += to_expand;
cur = idx_last_found + num_last_found + 1;
}
@@ -288,7 +309,7 @@ bool HeapRegionManager::is_on_preferred_index(uint region_index, uint preferred_
return region_node_index == preferred_node_index;
}
-uint HeapRegionManager::find_contiguous(size_t num, bool empty_only) {
+uint HeapRegionManager::find_contiguous(size_t num, bool empty_only, uint node) {
uint found = 0;
size_t length_found = 0;
uint cur = 0;
@@ -297,7 +318,12 @@ uint HeapRegionManager::find_contiguous(size_t num, bool empty_only) {
HeapRegion* hr = _regions.get_by_index(cur);
if ((!empty_only && !is_available(cur)) || (is_available(cur) && hr != NULL && hr->is_empty())) {
// This region is a potential candidate for allocation into.
- length_found++;
+ if (node != G1NUMA::AnyNodeIndex && hr != NULL && hr->node_index() != node) {
+ length_found = 0;
+ found = cur + 1;
+ } else {
+ length_found++;
+ }
} else {
// This region is not a candidate. The next region is the next possible one.
found = cur + 1;
@@ -306,13 +332,35 @@ uint HeapRegionManager::find_contiguous(size_t num, bool empty_only) {
cur++;
}
+ if (node != G1NUMA::AnyNodeIndex && length_found != num) {
+ found = 0;
+ length_found = 0;
+ cur = 0;
+ while (length_found < num && cur < max_length()) {
+ HeapRegion* hr = _regions.get_by_index(cur);
+ if ((!empty_only && !is_available(cur)) || (is_available(cur) && hr != NULL && hr->is_empty())) {
+ // This region is a potential candidate for allocation into.
+ length_found++;
+ } else {
+ // This region is not a candidate. The next region is the next possible one.
+ found = cur + 1;
+ length_found = 0;
+ }
+ cur++;
+ }
+ }
+
if (length_found == num) {
+ G1NUMA* numa = G1NUMA::numa();
for (uint i = found; i < (found + num); i++) {
HeapRegion* hr = _regions.get_by_index(i);
// sanity check
guarantee((!empty_only && !is_available(i)) || (is_available(i) && hr != NULL && hr->is_empty()),
"Found region sequence starting at " UINT32_FORMAT ", length " SIZE_FORMAT
" that is not empty at " UINT32_FORMAT ". Hr is " PTR_FORMAT, found, num, i, p2i(hr));
+ if (numa->is_humongous_region_enabled() && hr != NULL && hr->node_index() < numa->num_active_nodes()) {
+ numa->update_statistics(G1NUMAStats::NewRegionAlloc, node, hr->node_index());
+ }
}
return found;
} else {
diff --git a/src/hotspot/share/gc/g1/heapRegionManager.hpp b/src/hotspot/share/gc/g1/heapRegionManager.hpp
index 216fcbc92..3edc1a9fb 100644
--- a/src/hotspot/share/gc/g1/heapRegionManager.hpp
+++ b/src/hotspot/share/gc/g1/heapRegionManager.hpp
@@ -26,6 +26,7 @@
#define SHARE_VM_GC_G1_HEAPREGIONMANAGER_HPP
#include "gc/g1/g1BiasedArray.hpp"
+#include "gc/g1/g1NUMA.hpp"
#include "gc/g1/g1RegionToSpaceMapper.hpp"
#include "gc/g1/heapRegionSet.hpp"
#include "services/memoryUsage.hpp"
@@ -81,7 +82,7 @@ class HeapRegionManager: public CHeapObj<mtGC> {
G1RegionToSpaceMapper* _card_counts_mapper;
FreeRegionList _free_list;
-
+ G1RegionsOnNodes _humongous;
// Each bit in this bitmap indicates that the corresponding region is available
// for allocation.
CHeapBitMap _available_map;
@@ -95,10 +96,10 @@ class HeapRegionManager: public CHeapObj<mtGC> {
HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); }
HeapWord* heap_end() const {return _regions.end_address_mapped(); }
- void make_regions_available(uint index, uint num_regions = 1, WorkGang* pretouch_gang = NULL);
+ void make_regions_available(uint index, uint num_regions = 1, WorkGang* pretouch_gang = NULL, uint node = G1NUMA::AnyNodeIndex);
// Pass down commit calls to the VirtualSpace.
- void commit_regions(uint index, size_t num_regions = 1, WorkGang* pretouch_gang = NULL);
+ void commit_regions(uint index, size_t num_regions = 1, WorkGang* pretouch_gang = NULL, uint node = G1NUMA::AnyNodeIndex);
void uncommit_regions(uint index, size_t num_regions = 1);
// Notify other data structures about change in the heap layout.
@@ -108,7 +109,7 @@ class HeapRegionManager: public CHeapObj<mtGC> {
// the index of the first region or G1_NO_HRM_INDEX if the search was unsuccessful.
// If only_empty is true, only empty regions are considered.
// Searches from bottom to top of the heap, doing a first-fit.
- uint find_contiguous(size_t num, bool only_empty);
+ uint find_contiguous(size_t num, bool only_empty, uint node = G1NUMA::AnyNodeIndex);
// Finds the next sequence of unavailable regions starting from start_idx. Returns the
// length of the sequence found. If this result is zero, no such sequence could be found,
// otherwise res_idx indicates the start index of these regions.
@@ -212,17 +213,17 @@ public:
// Makes sure that the regions from start to start+num_regions-1 are available
// for allocation. Returns the number of regions that were committed to achieve
// this.
- uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers);
+ uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers, uint node = G1NUMA::AnyNodeIndex);
// Try to expand on the given node index.
virtual uint expand_on_preferred_node(uint node_index);
// Find a contiguous set of empty regions of length num. Returns the start index of
// that set, or G1_NO_HRM_INDEX.
- uint find_contiguous_only_empty(size_t num) { return find_contiguous(num, true); }
+ uint find_contiguous_only_empty(size_t num, uint node = G1NUMA::AnyNodeIndex) { return find_contiguous(num, true, node); }
// Find a contiguous set of empty or unavailable regions of length num. Returns the
// start index of that set, or G1_NO_HRM_INDEX.
- uint find_contiguous_empty_or_unavailable(size_t num) { return find_contiguous(num, false); }
+ uint find_contiguous_empty_or_unavailable(size_t num, uint node = G1NUMA::AnyNodeIndex) { return find_contiguous(num, false, node); }
HeapRegion* next_region_in_heap(const HeapRegion* r) const;
diff --git a/src/hotspot/share/gc/g1/heapRegionSet.hpp b/src/hotspot/share/gc/g1/heapRegionSet.hpp
index a495269da..71b89668a 100644
--- a/src/hotspot/share/gc/g1/heapRegionSet.hpp
+++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp
@@ -53,6 +53,7 @@ class HeapRegionSetChecker : public CHeapObj<mtGC> {
public:
// Verify MT safety for this HeapRegionSet.
virtual void check_mt_safety() = 0;
+ virtual bool is_correct_type(HeapRegion *hr) = 0;
};
// Base class for all the classes that represent heap region sets. It
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index fe7a5eff3..ce62c7ac7 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -299,6 +299,10 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G);
product(bool, UseNUMAInterleaving, false, \
"Interleave memory across NUMA nodes if available") \
\
+ experimental(bool, UseNUMAHumongous, false, \
+ "Allocate Humongous Regions in the same node if available" \
+ "Only used if UseNUMA is enabled.") \
+ \
product(size_t, NUMAInterleaveGranularity, 2*M, \
"Granularity to use for NUMA interleaving on Windows OS") \
range(os::vm_allocation_granularity(), NOT_LP64(2*G) LP64_ONLY(8192*G)) \
diff --git a/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAARMIO.java b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAARMIO.java
new file mode 100644
index 000000000..4394b5bbb
--- /dev/null
+++ b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAARMIO.java
@@ -0,0 +1,127 @@
+/*
+*Copyright (c) Huawei Technologies Co., Ltd. 2012-2019. All rights reserved.
+*/
+package com.huawei.openjdk.numa;
+/**
+ * @test TestNUMAARMIO
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms8G -Xmx8G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAARMIO 100 80000 80000 0 7 10000 10000 +UseNUMA -Xms16G -Xmx16G 70
+ * @summary open NUMA-Aware,test mermoy allocate and copy
+ * @author wangruishun
+ */
+
+/**
+ * @test TestNUMAARMIO
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms8G -Xmx8G -XX:-UseNUMA com.huawei.openjdk.numa.TestNUMAARMIO 100 80000 80000 0 7 10000 10000 -UseNUMA -Xms16G -Xmx16G 70
+ * @summary close NUMA-Aware,test mermoy allocate and copy
+ * @author wangruishun
+ */
+import jdk.test.lib.Asserts.*;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+
+public class TestNUMAARMIO {
+
+
+ public static void main(String[] args) throws Exception {
+ if (!TestNUMAAbstract.checkArgs(args)) {
+ System.err.println("[param error] please check your param");
+ throw new RuntimeException("args error!");
+ }
+ String flagStr = args[10];
+ float flag = Float.parseFloat(flagStr);
+ OutputAnalyzer output = TestNUMAAbstract.executeClass(args,ExeTest.class);
+ System.out.println(output.getStdout());
+ }
+
+
+
+ private static class ExeTest {
+
+ public static void main(String[] args) throws Exception {
+ int threadNum = Integer.valueOf(args[0]).intValue();
+ int minStore = Integer.valueOf(args[1]).intValue();
+ int maxStore = Integer.valueOf(args[2]).intValue();
+ int minThreadSleep = Integer.valueOf(args[3]).intValue();
+ int maxThreadSleep = Integer.valueOf(args[4]).intValue();
+ int minObjCount = Integer.valueOf(args[5]).intValue();
+ int maxObjCount = Integer.valueOf(args[6]).intValue();
+ long starTime = System.currentTimeMillis();
+ System.out.println("***********star time*************:" + starTime);
+ final CountDownLatch mDoneSignal = new CountDownLatch(threadNum);
+ //create thread
+ List<Thread> threadList = TestNUMAAbstract.createNUMABindThread(threadNum, minStore, maxStore, minThreadSleep, maxThreadSleep, minObjCount, maxObjCount,mDoneSignal,new TestNUMAAbstract(){
+ @Override
+ void threadRun(int minObjCount, int maxObjCount, int minStore, int maxStore, CountDownLatch mDoneSignal, int minThreadSleep, int maxThreadSleep) {
+ int randomObjNum = TestNUMAAbstract.randomNum(minObjCount, maxObjCount);
+ int count = 0;
+ while (count < randomObjNum) {
+ int randomStore = TestNUMAAbstract.randomNum(minStore, maxStore);
+ int[] arr = new int[randomStore];
+ //allocate mermory
+ for (int i = 0; i < arr.length; i++) {
+ arr[i] = i;
+ }
+ //copy mermory
+ int[] tem = new int[randomStore];
+ for (int i = 0; i < arr.length; i++) {
+ tem[i] = arr[i];
+ }
+ count++;
+ }
+ mDoneSignal.countDown();
+ }
+ });
+
+ TestNUMAAbstract.runNUMABindThread(threadList);
+ mDoneSignal.await();
+ long endTime = System.currentTimeMillis();
+ System.out.println("***********end time*************" + endTime);
+ System.out.println(String.format("Total thread count:%s", threadNum));
+ System.out.println(String.format("Min thread sleep:%s(um)", minThreadSleep));
+ System.out.println(String.format("Max thread sleep:%s(um)", maxThreadSleep));
+ System.out.println(String.format("Min RAM,int array length:%s", minStore));
+ System.out.println(String.format("Max RAM,int array length:%s", maxStore));
+ System.out.println(String.format("Min count of Obj:%s", minObjCount));
+ System.out.println(String.format("Max count of Obj:%s", maxObjCount));
+
+
+ double objTotalCount = threadNum*minObjCount;
+ double totalArm = objTotalCount*minStore*4;
+ //byte to KB
+ totalArm = totalArm/1024;
+ //KB to MB
+ totalArm = totalArm/1024;
+ System.out.println(String.format("allocate total ARM:%sMB", totalArm));
+ System.out.println(String.format("copy total ARM:%sMB", totalArm));
+ System.out.println("exe time:" + (endTime - starTime));
+ }
+
+
+
+
+
+ }
+}
+
diff --git a/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAbstract.java b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAbstract.java
new file mode 100644
index 000000000..31eb393f6
--- /dev/null
+++ b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAbstract.java
@@ -0,0 +1,178 @@
+/*
+* Copyright (c) Huawei Technologies Co., Ltd. 2012-2019. All rights
+reserved.
+*/
+package com.huawei.openjdk.numa;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+import jdk.test.lib.Asserts.*;
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import sun.hotspot.WhiteBox;
+/**
+ * @summary Utility class.
+ * @author wangruishun
+ */
+public class TestNUMAAbstract {
+
+
+ private static final int ARGS_LEN_LIMIT = 11;
+
+ void threadRun(int minObjCount,int maxObjCount,int minStore,int maxStore,CountDownLatch mDoneSignal,int minThreadSleep, int maxThreadSleep){
+
+ }
+ /**
+ * get random from closed interval
+ *
+ * @param minNum min
+ * @param maxNum max
+ * @return random
+ */
+ public static int randomNum(int minNum, int maxNum) {
+ if (minNum == maxNum) {
+ return minNum;
+ }
+ Random random = new Random();
+ int randomNum = random.nextInt((maxNum - minNum) + 1) + minNum;
+ return randomNum;
+ }
+
+ /**
+ * start all thread
+ * @param createNUMABindThread thread list
+ */
+ public static void runNUMABindThread(List<Thread> createNUMABindThread) {
+ for (Thread thread : createNUMABindThread) {
+ try {
+ thread.start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * create thread and The execution content is provided by the caller
+ *
+ * @param maxThreadNum maxThreadNum
+ * @param minStore minStore
+ * @param maxStore maxStore
+ * @param minThreadSleep minThreadSleep
+ * @param maxThreadSleep maxThreadSleep
+ * @param minObjCount minObjCount
+ * @param maxObjCount maxObjCount
+ * @return list
+ */
+ public static List<Thread> createNUMABindThread(int maxThreadNum, int minStore, int maxStore, int minThreadSleep, int maxThreadSleep, int minObjCount, int maxObjCount, CountDownLatch mDoneSignal,TestNUMAAbstract testNUMAAbstract) {
+ System.gc();
+ System.out.println("-------init gc over ------------");
+ System.out.println(String.format("args[0]:Total thread count:%s", maxThreadNum));
+ System.out.println(String.format("args[1]:Min thread sleep:%s(um)", minThreadSleep));
+ System.out.println(String.format("args[2]:Max thread sleep:%s(um)", maxThreadSleep));
+ System.out.println(String.format("args[3]:Min RAM,int array length:%s", minStore));
+ System.out.println(String.format("args[4]:Max RAM,int array length:%s", maxStore));
+ System.out.println(String.format("args[5]:Min count of Obj:%s", minObjCount));
+ System.out.println(String.format("args[6]:Max count of Obj:%s", maxObjCount));
+ List<Thread> list = new ArrayList<>();
+ int i = 0;
+ while (i < maxThreadNum) {
+ Thread createObj = new TestNUMABindThread(minStore, maxStore, minThreadSleep, maxThreadSleep, minObjCount, maxObjCount, mDoneSignal,testNUMAAbstract);
+ list.add(createObj);
+ i++;
+ }
+ return list;
+ }
+
+
+ /**
+ * execute class
+ *
+ * @param args the param of main
+ * @param exeClass calss name
+ * @throws Exception
+ */
+ public static OutputAnalyzer executeClass(String[] args,Class exeClass) throws Exception {
+ final String[] arguments = {
+ "-Xbootclasspath/a:.",
+ "-XX:" + args[7],
+ args[8],
+ args[9],
+ "-Xlog:gc*=info",
+ exeClass.getName(),
+ args[0],
+ args[1],
+ args[2],
+ args[3],
+ args[4],
+ args[5],
+ args[6]
+ };
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(arguments);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ return output;
+ }
+
+ /**
+ * param check
+ * @param args
+ * @return
+ */
+ public static boolean checkArgs(String[] args) {
+ if (args == null || args.length != ARGS_LEN_LIMIT) {
+ System.out.println("args[0]:Total thread count");
+ System.out.println("args[1]:Min thread sleep(um)");
+ System.out.println("args[2]:Max thread sleep(um)");
+ System.out.println("args[3]:Min RAM,int array length");
+ System.out.println("args[4]:Max RAM,int array length");
+ System.out.println("args[5]:Min count of Obj");
+ System.out.println("args[6]:Max count of Obj");
+ System.out.println("args[7]:NUMA is open,+UseNUMA/-UseNUMA");
+ return false;
+ }
+ return true;
+ }
+}
+
+
+class TestNUMABindThread extends Thread {
+ private int minStore;
+ private int maxStore;
+ private int minThreadSleep;
+ private int maxThreadSleep;
+ private int minObjCount;
+ private int maxObjCount;
+ private CountDownLatch mDoneSignal;
+ private TestNUMAAbstract testNUMAAbstract;
+
+ /**
+ * @param minStore min store
+ * @param maxStore max store
+ * @param minThreadSleep sleep time(um)
+ * @param maxThreadSleep sleep time(um)
+ * @param minObjCount the count of obj in one thread
+ * @param maxObjCount the count of obj in one thread
+ */
+ public TestNUMABindThread(int minStore, int maxStore, int minThreadSleep, int maxThreadSleep, int minObjCount, int maxObjCount, CountDownLatch mDoneSignal, TestNUMAAbstract testNUMAAbstract) {
+ this.minStore = minStore;
+ this.maxStore = maxStore;
+ this.minThreadSleep = minThreadSleep;
+ this.maxThreadSleep = maxThreadSleep;
+ this.minObjCount = minObjCount;
+ this.maxObjCount = maxObjCount;
+ this.mDoneSignal = mDoneSignal;
+ this.testNUMAAbstract = testNUMAAbstract;
+ }
+
+ @Override
+ public void run() {
+ testNUMAAbstract.threadRun(minObjCount, maxObjCount, minStore, maxStore, mDoneSignal,minThreadSleep,maxThreadSleep);
+ mDoneSignal.countDown();
+ }
+}
\ No newline at end of file
diff --git a/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAllocate.java b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAllocate.java
new file mode 100644
index 000000000..a00e6dad4
--- /dev/null
+++ b/test/jtreg-ext/com/huawei/openjdk/numa/TestNUMAAllocate.java
@@ -0,0 +1,208 @@
+/*
+* Copyright (c) Huawei Technologies Co., Ltd. 2012-2019. All rights
+reserved.
+*/
+package com.huawei.openjdk.numa;
+/**
+ * @test TestNUMAAllocate
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms8G -Xmx8G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAAllocate 1500 77000 80000 0 7 10000 10000 +UseNUMA -Xms8G -Xmx8G 70
+ * @summary opem NUMA-Aware,Memory allocate distribution ratio exceeds 70%
+ * @author wangruishun
+ */
+/**
+ * @test TestNUMAAllocate
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms16G -Xmx16G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAAllocate 1 6000000 9000000 0 0 100 100 +UseNUMA -Xms8G -Xmx16G 20
+ * @summary opem NUMA-Aware,Memory allocate distribution ratio exceeds 20%,one thread Humongous.
+ * @author wangruishun
+ */
+/**
+ * @test TestNUMAAllocate
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms16G -Xmx16G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAAllocate 5 800000 1000000 0 7 100 100 +UseNUMA -Xms256M -Xmx16G 45
+ * @summary opem NUMA-Aware,Memory allocate distribution ratio exceeds 45%,5 thread,Humongous
+ * @author wangruishun
+ */
+
+/**
+ * @test TestNUMAAllocate
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms16G -Xmx16G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAAllocate 5 800000 1000000 0 7 100 100 +UseNUMA -Xms256M -Xmx16G 45
+ * @summary opem NUMA-Aware,Memory allocate distribution ratio exceeds 45%,5 thread,Humongous
+ * @author wangruishun
+ */
+
+
+/**
+ * @test TestNUMAAllocate
+ * @key gc
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @build com.huawei.openjdk.numa.TestNUMAAbstract
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xlog:gc*=info -Xms8G -Xmx8G -XX:+UseNUMA com.huawei.openjdk.numa.TestNUMAAllocate 120 77000 80000 0 7 150 150 +UseNUMA -Xms8G -Xmx8G 70
+ * @summary opem NUMA-Aware,Memory allocate distribution ratio exceeds 70%
+ * @author wangruishun
+ */
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.Asserts.*;
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import sun.hotspot.WhiteBox;
+
+
+public class TestNUMAAllocate{
+
+ private static final int ARGS_LEN_LIMIT = 11;
+
+ public static void main(String[] args) throws Exception {
+ if (!TestNUMAAbstract.checkArgs(args)) {
+ System.err.println("[param error] please check your param");
+ throw new RuntimeException("args error!");
+ }
+ //ratio
+ String flagStr = args[10];
+ float flag = Float.parseFloat(flagStr);
+ //execute program and get stdout
+ OutputAnalyzer output = TestNUMAAbstract.executeClass(args,GClogTest.class);
+ //check print
+ checkPattern(".*Placement match ratio:*", output.getStdout(),flag);
+ }
+
+
+
+ /**
+ * Check if the string matches
+ *
+ * @param pattern string
+ * @param what string
+ * @param flag ratio
+ * @throws Exception
+ */
+ private static void checkPattern(String pattern, String what, float flag) throws Exception {
+ String[] arr = what.split(System.lineSeparator());
+ boolean isMatch = false;
+ float maxPercent = 0f;
+ for (String line : arr) {
+ Pattern r = Pattern.compile(pattern);
+ Matcher m = r.matcher(line);
+ if (m.find()) {
+ isMatch = true;
+ Float percentLine = getPercentByLog(line);
+ if (percentLine > maxPercent) {
+ maxPercent = percentLine;
+ }
+ }
+ }
+ System.out.println(String.format("NUMA percent:%s", maxPercent));
+ if (!isMatch) {
+ throw new RuntimeException("Could not find pattern " + pattern + " in output");
+ }
+ if (maxPercent < flag) {
+ throw new RuntimeException("MUMA Seems to fail to start ");
+ }
+ }
+
+ /**
+ * get ration by gclog
+ *
+ * @param line
+ * @return
+ */
+ private static Float getPercentByLog(String line) {
+ if (null == line || "".equals(line)) {
+ return 0f;
+ }
+ //[1.631s][info][gc,heap,numa ] GC(23) Placement match ratio: 5% 555/10618 (0: 62% 243/392, 1: 53% 265/498, 2: 100% 11/11, 3: 100% 36/36)
+ Pattern pattern = Pattern.compile(".\\d%|[1-9]*%|100%");
+ Matcher matcher = pattern.matcher(line);
+ Float percent = 0f;
+ if(matcher.find()){
+ String percentStr = matcher.group(0);
+ percentStr = percentStr.substring(0,percentStr.length()-1);
+ percent = Float.parseFloat(percentStr);
+ }
+ return percent;
+ }
+
+
+ private static class GClogTest {
+ public static void main(String[] args) throws Exception {
+ int threadNum = Integer.valueOf(args[0]).intValue();
+ int minStore = Integer.valueOf(args[1]).intValue();
+ int maxStore = Integer.valueOf(args[2]).intValue();
+ int minThreadSleep = Integer.valueOf(args[3]).intValue();
+ int maxThreadSleep = Integer.valueOf(args[4]).intValue();
+ int minObjCount = Integer.valueOf(args[5]).intValue();
+ int maxObjCount = Integer.valueOf(args[6]).intValue();
+ long starTime = System.currentTimeMillis();
+ System.out.println("***********star time*************:" + starTime);
+ final CountDownLatch mDoneSignal = new CountDownLatch(threadNum);
+ List<Thread> threadList = TestNUMAAbstract.createNUMABindThread(threadNum, minStore, maxStore, minThreadSleep, maxThreadSleep, minObjCount, maxObjCount,mDoneSignal,new TestNUMAAbstract(){
+ @Override
+ void threadRun(int minObjCount, int maxObjCount, int minStore, int maxStore, CountDownLatch mDoneSignal, int minThreadSleep, int maxThreadSleep) {
+ int randomObjNum = TestNUMAAbstract.randomNum(minObjCount, maxObjCount);
+ int count = 0;
+ while (count < randomObjNum) {
+ int randomStore = TestNUMAAbstract.randomNum(minStore, maxStore);
+ int[] arr = new int[randomStore];
+ int[] tem = new int[1];
+ for (int i = 0; i < arr.length; i++) {
+ tem[0] = arr[i];
+ }
+
+ count++;
+ try {
+ int threadSleep = TestNUMAAbstract.randomNum(minThreadSleep, maxThreadSleep);
+ TimeUnit.MICROSECONDS.sleep(threadSleep);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ mDoneSignal.countDown();
+ }
+ });
+ TestNUMAAbstract.runNUMABindThread(threadList);
+ mDoneSignal.await();
+ long endTime = System.currentTimeMillis();
+ System.out.println("***********end time*************" + endTime);
+ System.out.println("***********result time*************" + (starTime - endTime));
+ }
+
+ }
+}
+
+
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化