Skip to content

Commit f74fbfe

Browse files
committed
8357449: ZGC: Multiple medium page sizes
Reviewed-by: stefank, jsikstro
1 parent efeb050 commit f74fbfe

19 files changed

+392
-58
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ typedef ZValue<ZPerNUMAStorage, ZPartition> ZPerNUMAZPartition;
120120
declare_constant(ZPageType::small) \
121121
declare_constant(ZPageType::medium) \
122122
declare_constant(ZPageType::large) \
123+
declare_constant(ZPageSizeSmallShift) \
124+
declare_constant(ZPageSizeMediumMaxShift) \
123125
declare_constant(ZObjectAlignmentMediumShift) \
124126
declare_constant(ZObjectAlignmentLargeShift)
125127

126128
#define VM_LONG_CONSTANTS_Z(declare_constant) \
127129
declare_constant(ZGranuleSizeShift) \
128-
declare_constant(ZPageSizeSmallShift) \
129-
declare_constant(ZPageSizeMediumShift) \
130130
declare_constant(ZAddressOffsetShift) \
131131
declare_constant(ZAddressOffsetBits) \
132132
declare_constant(ZAddressOffsetMask) \

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

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,25 @@
3131
// Allocation flags layout
3232
// -----------------------
3333
//
34-
// 7 1 0
35-
// +------+-+-+
36-
// |000000|1|1|
37-
// +------+-+-+
34+
// 7 2 1 0
35+
// +-----+-+-+-+
36+
// |00000|1|1|1|
37+
// +-----+-+-+-+
38+
// | | | |
39+
// | | | * 0-0 Non-Blocking Flag (1-bit)
3840
// | | |
39-
// | | * 0-0 Non-Blocking Flag (1-bit)
41+
// | | * 1-1 GC Relocation Flag (1-bit)
4042
// | |
41-
// | * 1-1 GC Relocation Flag (1-bit)
43+
// | * 2-2 Fast Medium Flag (1-bit)
4244
// |
43-
// * 7-2 Unused (6-bits)
45+
// * 7-3 Unused (5-bits)
4446
//
4547

4648
class ZAllocationFlags {
4749
private:
4850
typedef ZBitField<uint8_t, bool, 0, 1> field_non_blocking;
4951
typedef ZBitField<uint8_t, bool, 1, 1> field_gc_relocation;
52+
typedef ZBitField<uint8_t, bool, 2, 1> field_fast_medium;
5053

5154
uint8_t _flags;
5255

@@ -62,13 +65,21 @@ class ZAllocationFlags {
6265
_flags |= field_gc_relocation::encode(true);
6366
}
6467

68+
void set_fast_medium() {
69+
_flags |= field_fast_medium::encode(true);
70+
}
71+
6572
bool non_blocking() const {
6673
return field_non_blocking::decode(_flags);
6774
}
6875

6976
bool gc_relocation() const {
7077
return field_gc_relocation::decode(_flags);
7178
}
79+
80+
bool fast_medium() const {
81+
return field_fast_medium::decode(_flags);
82+
}
7283
};
7384

7485
#endif // SHARE_GC_Z_ZALLOCATIONFLAGS_HPP

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ void ZArguments::initialize() {
162162
uint tenuring_threshold;
163163
for (tenuring_threshold = 0; tenuring_threshold < MaxTenuringThreshold; ++tenuring_threshold) {
164164
// Reduce the number of object ages, if the resulting garbage is too high
165-
const size_t medium_page_overhead = ZPageSizeMedium * tenuring_threshold;
166-
const size_t small_page_overhead = ZPageSizeSmall * ConcGCThreads * tenuring_threshold;
167-
if (small_page_overhead + medium_page_overhead >= ZHeuristics::significant_young_overhead()) {
165+
const size_t per_age_overhead = ZHeuristics::relocation_headroom();
166+
if (per_age_overhead * tenuring_threshold >= ZHeuristics::significant_young_overhead()) {
168167
break;
169168
}
170169
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323

2424
#include "gc/z/zGlobals.hpp"
2525

26-
size_t ZPageSizeMediumShift;
27-
size_t ZPageSizeMedium;
26+
int ZPageSizeMediumMaxShift;
27+
size_t ZPageSizeMediumMax;
28+
size_t ZPageSizeMediumMin;
29+
bool ZPageSizeMediumEnabled;
2830

2931
size_t ZObjectSizeLimitMedium;
3032

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ const size_t ZVirtualToPhysicalRatio = 16; // 16:1
4242
const size_t ZMaxVirtualReservations = 100; // Each reservation at least 1% of total
4343

4444
// Page size shifts
45-
const size_t ZPageSizeSmallShift = ZGranuleSizeShift;
46-
extern size_t ZPageSizeMediumShift;
45+
const int ZPageSizeSmallShift = (int)ZGranuleSizeShift;
46+
extern int ZPageSizeMediumMaxShift;
4747

4848
// Page sizes
4949
const size_t ZPageSizeSmall = (size_t)1 << ZPageSizeSmallShift;
50-
extern size_t ZPageSizeMedium;
50+
extern size_t ZPageSizeMediumMax;
51+
extern size_t ZPageSizeMediumMin;
52+
extern bool ZPageSizeMediumEnabled;
5153

5254
// Object size limits
5355
const size_t ZObjectSizeLimitSmall = ZPageSizeSmall / 8; // 12.5% max waste

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,15 @@ void ZHeap::print_globals_on(outputStream* st) const {
364364
st->print_cr(" Old Collection: %s/%u", ZGeneration::old()->phase_to_string(), ZGeneration::old()->seqnum());
365365
st->print_cr(" Offset Max: " EXACTFMT " (" PTR_FORMAT ")", EXACTFMTARGS(ZAddressOffsetMax), ZAddressOffsetMax);
366366
st->print_cr(" Page Size Small: %zuM", ZPageSizeSmall / M);
367-
st->print_cr(" Page Size Medium: %zuM", ZPageSizeMedium / M);
367+
if (ZPageSizeMediumEnabled) {
368+
if (ZPageSizeMediumMin == ZPageSizeMediumMax) {
369+
st->print_cr(" Page Size Medium: %zuM", ZPageSizeMediumMax / M);
370+
} else {
371+
st->print_cr(" Page Size Medium: Range [%zuM, %zuM]", ZPageSizeMediumMin / M, ZPageSizeMediumMax / M);
372+
}
373+
} else {
374+
st->print_cr(" Page Size Medium: N/A");
375+
}
368376
st->cr();
369377
st->print_cr("ZGC Metadata Bits:");
370378
st->print_cr(" LoadGood: " PTR_FORMAT, ZPointerLoadGoodMask);

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "gc/z/zHeuristics.hpp"
2929
#include "runtime/globals.hpp"
3030
#include "runtime/os.hpp"
31+
#include "utilities/align.hpp"
3132
#include "utilities/globalDefinitions.hpp"
3233
#include "utilities/powerOfTwo.hpp"
3334

@@ -44,18 +45,22 @@ void ZHeuristics::set_medium_page_size() {
4445

4546
if (size > ZPageSizeSmall) {
4647
// Enable medium pages
47-
ZPageSizeMedium = size;
48-
ZPageSizeMediumShift = (size_t)log2i_exact(ZPageSizeMedium);
49-
ZObjectSizeLimitMedium = ZPageSizeMedium / 8;
50-
ZObjectAlignmentMediumShift = (int)ZPageSizeMediumShift - 13;
48+
ZPageSizeMediumMax = size;
49+
ZPageSizeMediumMaxShift = log2i_exact(ZPageSizeMediumMax);
50+
ZObjectSizeLimitMedium = ZPageSizeMediumMax / 8;
51+
ZObjectAlignmentMediumShift = ZPageSizeMediumMaxShift - 13;
5152
ZObjectAlignmentMedium = 1 << ZObjectAlignmentMediumShift;
53+
ZPageSizeMediumEnabled = true;
54+
ZPageSizeMediumMin = ZUseMediumPageSizeRange
55+
? align_up(ZObjectSizeLimitMedium, ZGranuleSize)
56+
: ZPageSizeMediumMax;
5257
}
5358
}
5459

5560
size_t ZHeuristics::relocation_headroom() {
5661
// Calculate headroom needed to avoid in-place relocation. Each worker will try
5762
// to allocate a small page, and all workers will share a single medium page.
58-
return (ConcGCThreads * ZPageSizeSmall) + ZPageSizeMedium;
63+
return (ConcGCThreads * ZPageSizeSmall) + ZPageSizeMediumMax;
5964
}
6065

6166
bool ZHeuristics::use_per_cpu_shared_small_pages() {

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ ZVirtualMemory ZMappedCache::remove_vmem(ZMappedCacheEntry* const entry, size_t
414414
template <typename SelectFunction, typename ConsumeFunction>
415415
bool ZMappedCache::try_remove_vmem_size_class(size_t min_size, SelectFunction select, ConsumeFunction consume) {
416416
new_max_size:
417+
if (_size < min_size) {
418+
// Not enough left in cache to satisfy the min_size
419+
return false;
420+
}
421+
417422
// Query the max select size possible given the size of the cache
418423
const size_t max_size = select(_size);
419424

@@ -648,6 +653,37 @@ ZVirtualMemory ZMappedCache::remove_contiguous(size_t size) {
648653
return result;
649654
}
650655

656+
ZVirtualMemory ZMappedCache::remove_contiguous_power_of_2(size_t min_size, size_t max_size) {
657+
precond(is_aligned(min_size, ZGranuleSize));
658+
precond(is_power_of_2(min_size));
659+
precond(is_aligned(max_size, ZGranuleSize));
660+
precond(is_power_of_2(max_size));
661+
precond(min_size <= max_size);
662+
663+
ZVirtualMemory result;
664+
665+
const auto select_size_fn = [&](size_t size) {
666+
// Always select a power of 2 within the [min_size, max_size] interval.
667+
return clamp(round_down_power_of_2(size), min_size, max_size);
668+
};
669+
670+
const auto consume_vmem_fn = [&](ZVirtualMemory vmem) {
671+
assert(result.is_null(), "only consume once");
672+
assert(min_size <= vmem.size() && vmem.size() <= max_size,
673+
"Must be %zu <= %zu <= %zu", min_size, vmem.size(), max_size);
674+
assert(is_power_of_2(vmem.size()), "Must be power_of_2(%zu)", vmem.size());
675+
676+
result = vmem;
677+
678+
// Only require one vmem
679+
return true;
680+
};
681+
682+
scan_remove_vmem<RemovalStrategy::SizeClasses>(min_size, select_size_fn, consume_vmem_fn);
683+
684+
return result;
685+
}
686+
651687
size_t ZMappedCache::remove_discontiguous(size_t size, ZArray<ZVirtualMemory>* out) {
652688
return remove_discontiguous_with_strategy<RemovalStrategy::SizeClasses>(size, out);
653689
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class ZMappedCache {
129129
void insert(const ZVirtualMemory& vmem);
130130

131131
ZVirtualMemory remove_contiguous(size_t size);
132+
ZVirtualMemory remove_contiguous_power_of_2(size_t min_size, size_t max_size);
132133
size_t remove_discontiguous(size_t size, ZArray<ZVirtualMemory>* out);
133134

134135
size_t reset_min();

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,26 @@ zaddress ZObjectAllocator::alloc_object_in_medium_page(size_t size,
140140
ZAllocationFlags non_blocking_flags = flags;
141141
non_blocking_flags.set_non_blocking();
142142

143-
addr = alloc_object_in_shared_page(shared_medium_page, ZPageType::medium, ZPageSizeMedium, size, non_blocking_flags);
143+
if (ZPageSizeMediumMin != ZPageSizeMediumMax) {
144+
assert(ZPageSizeMediumEnabled, "must be enabled");
145+
// We attempt a fast medium allocations first. Which will only succeed
146+
// if a page in the range [ZPageSizeMediumMin, ZPageSizeMediumMax] can
147+
// be allocated without any expensive syscalls, directly from the cache.
148+
ZAllocationFlags fast_medium_flags = non_blocking_flags;
149+
fast_medium_flags.set_fast_medium();
150+
addr = alloc_object_in_shared_page(shared_medium_page, ZPageType::medium, ZPageSizeMediumMax, size, fast_medium_flags);
151+
}
152+
153+
if (is_null(addr)) {
154+
addr = alloc_object_in_shared_page(shared_medium_page, ZPageType::medium, ZPageSizeMediumMax, size, non_blocking_flags);
155+
}
156+
144157
}
145158

146159
if (is_null(addr) && !flags.non_blocking()) {
147160
// The above allocation attempts failed and this allocation should stall
148161
// until memory is available. Redo the allocation with blocking enabled.
149-
addr = alloc_object_in_shared_page(shared_medium_page, ZPageType::medium, ZPageSizeMedium, size, flags);
162+
addr = alloc_object_in_shared_page(shared_medium_page, ZPageType::medium, ZPageSizeMediumMax, size, flags);
150163
}
151164

152165
return addr;

0 commit comments

Comments
 (0)