Skip to content

Commit b39c736

Browse files
committed
8359683: ZGC: NUMA-Aware Relocation
Reviewed-by: aboldtch, sjohanss
1 parent 88c3979 commit b39c736

15 files changed

+244
-98
lines changed

src/hotspot/share/gc/z/zArray.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class ZArrayIteratorImpl : public StackObj {
9191
ZArrayIteratorImpl(const ZArray<T>* array);
9292

9393
bool next(T* elem);
94+
95+
template <typename Function, typename... Args>
96+
bool next_if(T* elem, Function predicate, Args&&... args);
97+
9498
bool next_index(size_t* index);
9599

96100
T index_to_elem(size_t index);

src/hotspot/share/gc/z/zArray.inline.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,20 @@ inline bool ZArrayIteratorImpl<T, Parallel>::next(T* elem) {
161161
return false;
162162
}
163163

164+
template <typename T, bool Parallel>
165+
template <typename Function, typename... Args>
166+
inline bool ZArrayIteratorImpl<T, Parallel>::next_if(T* elem, Function predicate, Args&&... args) {
167+
size_t index;
168+
while (next_index(&index)) {
169+
if (predicate(index_to_elem(index), args...)) {
170+
*elem = index_to_elem(index);
171+
return true;
172+
}
173+
}
174+
175+
return false;
176+
}
177+
164178
template <typename T, bool Parallel>
165179
inline bool ZArrayIteratorImpl<T, Parallel>::next_index(size_t* index) {
166180
if (Parallel) {

src/hotspot/share/gc/z/zForwarding.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -59,6 +59,7 @@ class ZForwarding {
5959
const size_t _object_alignment_shift;
6060
const AttachedArray _entries;
6161
ZPage* const _page;
62+
const uint32_t _partition_id;
6263
const ZPageAge _from_age;
6364
const ZPageAge _to_age;
6465
volatile bool _claimed;
@@ -108,6 +109,8 @@ class ZForwarding {
108109
size_t size() const;
109110
size_t object_alignment_shift() const;
110111

112+
uint32_t partition_id() const;
113+
111114
bool is_promotion() const;
112115

113116
// Visit from-objects

src/hotspot/share/gc/z/zForwarding.inline.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,7 @@ inline ZForwarding::ZForwarding(ZPage* page, ZPageAge to_age, size_t nentries)
6161
_object_alignment_shift(page->object_alignment_shift()),
6262
_entries(nentries),
6363
_page(page),
64+
_partition_id(page->single_partition_id()),
6465
_from_age(page->age()),
6566
_to_age(to_age),
6667
_claimed(false),
@@ -102,6 +103,10 @@ inline size_t ZForwarding::object_alignment_shift() const {
102103
return _object_alignment_shift;
103104
}
104105

106+
inline uint32_t ZForwarding::partition_id() const {
107+
return _partition_id;
108+
}
109+
105110
inline bool ZForwarding::is_promotion() const {
106111
return _from_age != ZPageAge::old &&
107112
_to_age == ZPageAge::old;

src/hotspot/share/gc/z/zHeap.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ void ZHeap::account_undo_alloc_page(ZPage* page) {
250250
p2i(Thread::current()), ZUtils::thread_name(), p2i(page), page->size());
251251
}
252252

253-
ZPage* ZHeap::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) {
254-
ZPage* const page = _page_allocator.alloc_page(type, size, flags, age);
253+
ZPage* ZHeap::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age, uint32_t preferred_partition) {
254+
ZPage* const page = _page_allocator.alloc_page(type, size, flags, age, preferred_partition);
255255
if (page != nullptr) {
256256
// Insert page table entry
257257
_page_table.insert(page);

src/hotspot/share/gc/z/zHeap.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class ZHeap {
108108
void mark_flush(Thread* thread);
109109

110110
// Page allocation
111-
ZPage* alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age);
111+
ZPage* alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age, uint32_t preferred_partition);
112112
void undo_alloc_page(ZPage* page);
113113
void free_page(ZPage* page);
114114
size_t free_empty_pages(ZGenerationId id, const ZArray<ZPage*>* pages);

src/hotspot/share/gc/z/zHeuristics.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "gc/z/zCPU.inline.hpp"
2727
#include "gc/z/zGlobals.hpp"
2828
#include "gc/z/zHeuristics.hpp"
29+
#include "gc/z/zNUMA.inline.hpp"
2930
#include "runtime/globals.hpp"
3031
#include "runtime/os.hpp"
3132
#include "utilities/align.hpp"
@@ -58,9 +59,11 @@ void ZHeuristics::set_medium_page_size() {
5859
}
5960

6061
size_t ZHeuristics::relocation_headroom() {
61-
// Calculate headroom needed to avoid in-place relocation. Each worker will try
62-
// to allocate a small page, and all workers will share a single medium page.
63-
return (ConcGCThreads * ZPageSizeSmall) + ZPageSizeMediumMax;
62+
// Calculate headroom needed to avoid in-place relocation. For each NUMA node,
63+
// each worker will try to allocate a small page, and all workers will share a
64+
// single medium page.
65+
const size_t per_numa_headroom = (ConcGCThreads * ZPageSizeSmall) + ZPageSizeMediumMax;
66+
return per_numa_headroom * ZNUMA::count();
6467
}
6568

6669
bool ZHeuristics::use_per_cpu_shared_small_pages() {

src/hotspot/share/gc/z/zObjectAllocator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ ZPage* const* ZObjectAllocator::PerAge::shared_small_page_addr() const {
5353
}
5454

5555
ZPage* ZObjectAllocator::PerAge::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags) {
56-
return ZHeap::heap()->alloc_page(type, size, flags, _age);
56+
return ZHeap::heap()->alloc_page(type, size, flags, _age, ZNUMA::id());
5757
}
5858

5959
void ZObjectAllocator::PerAge::undo_alloc_page(ZPage* page) {

src/hotspot/share/gc/z/zPage.inline.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ inline const ZVirtualMemory& ZPage::virtual_memory() const {
157157
}
158158

159159
inline uint32_t ZPage::single_partition_id() const {
160+
assert(!is_multi_partition(), "Don't fetch single partition id if page is multi-partition");
160161
return _single_partition_id;
161162
}
162163

src/hotspot/share/gc/z/zPageAllocator.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -412,28 +412,30 @@ class ZPageAllocation : public StackObj {
412412
const Ticks _start_timestamp;
413413
const uint32_t _young_seqnum;
414414
const uint32_t _old_seqnum;
415-
const uint32_t _initiating_numa_id;
415+
const uint32_t _preferred_partition;
416416
bool _is_multi_partition;
417417
ZSinglePartitionAllocation _single_partition_allocation;
418418
ZMultiPartitionAllocation _multi_partition_allocation;
419419
ZListNode<ZPageAllocation> _node;
420420
ZFuture<bool> _stall_result;
421421

422422
public:
423-
ZPageAllocation(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age)
423+
ZPageAllocation(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age, uint32_t preferred_partition)
424424
: _type(type),
425425
_requested_size(size),
426426
_flags(flags),
427427
_age(age),
428428
_start_timestamp(Ticks::now()),
429429
_young_seqnum(ZGeneration::young()->seqnum()),
430430
_old_seqnum(ZGeneration::old()->seqnum()),
431-
_initiating_numa_id(ZNUMA::id()),
431+
_preferred_partition(preferred_partition),
432432
_is_multi_partition(false),
433433
_single_partition_allocation(size),
434434
_multi_partition_allocation(size),
435435
_node(),
436-
_stall_result() {}
436+
_stall_result() {
437+
assert(_preferred_partition < ZNUMA::count(), "Preferred partition out-of-bounds (0 <= %d < %d)", _preferred_partition, ZNUMA::count());
438+
}
437439

438440
void reset_for_retry() {
439441
_is_multi_partition = false;
@@ -474,8 +476,8 @@ class ZPageAllocation : public StackObj {
474476
return _old_seqnum;
475477
}
476478

477-
uint32_t initiating_numa_id() const {
478-
return _initiating_numa_id;
479+
uint32_t preferred_partition() const {
480+
return _preferred_partition;
479481
}
480482

481483
bool is_multi_partition() const {
@@ -1397,10 +1399,10 @@ static void check_out_of_memory_during_initialization() {
13971399
}
13981400
}
13991401

1400-
ZPage* ZPageAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) {
1402+
ZPage* ZPageAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age, uint32_t preferred_partition) {
14011403
EventZPageAllocation event;
14021404

1403-
ZPageAllocation allocation(type, size, flags, age);
1405+
ZPageAllocation allocation(type, size, flags, age, preferred_partition);
14041406

14051407
// Allocate the page
14061408
ZPage* const page = alloc_page_inner(&allocation);
@@ -1548,7 +1550,7 @@ bool ZPageAllocator::claim_capacity(ZPageAllocation* allocation) {
15481550
}
15491551

15501552
// Round robin single-partition claiming
1551-
const uint32_t start_numa_id = allocation->initiating_numa_id();
1553+
const uint32_t start_numa_id = allocation->preferred_partition();
15521554
const uint32_t start_partition = start_numa_id;
15531555
const uint32_t num_partitions = _partitions.count();
15541556

@@ -1560,7 +1562,7 @@ bool ZPageAllocator::claim_capacity(ZPageAllocation* allocation) {
15601562
}
15611563
}
15621564

1563-
if (!is_multi_partition_enabled() || sum_available() < allocation->size()) {
1565+
if (!is_multi_partition_allowed(allocation)) {
15641566
// Multi-partition claiming is not possible
15651567
return false;
15661568
}
@@ -1578,7 +1580,7 @@ bool ZPageAllocator::claim_capacity(ZPageAllocation* allocation) {
15781580
}
15791581

15801582
bool ZPageAllocator::claim_capacity_fast_medium(ZPageAllocation* allocation) {
1581-
const uint32_t start_node = allocation->initiating_numa_id();
1583+
const uint32_t start_node = allocation->preferred_partition();
15821584
const uint32_t numa_nodes = ZNUMA::count();
15831585

15841586
for (uint32_t i = 0; i < numa_nodes; ++i) {
@@ -2191,6 +2193,12 @@ bool ZPageAllocator::is_multi_partition_enabled() const {
21912193
return _virtual.is_multi_partition_enabled();
21922194
}
21932195

2196+
bool ZPageAllocator::is_multi_partition_allowed(const ZPageAllocation* allocation) const {
2197+
return is_multi_partition_enabled() &&
2198+
allocation->type() == ZPageType::large &&
2199+
allocation->size() <= sum_available();
2200+
}
2201+
21942202
const ZPartition& ZPageAllocator::partition_from_partition_id(uint32_t numa_id) const {
21952203
return _partitions.get(numa_id);
21962204
}

0 commit comments

Comments
 (0)