Skip to content

Commit 3e89f72

Browse files
plidenalbertnetymk
andcommitted
8255237: ZGC: Bulk free garbage pages during relocation set selection
Co-authored-by: Albert Mingkun Yang <ayang@openjdk.org> Co-authored-by: Per Liden <pliden@openjdk.org> Reviewed-by: ayang, eosterlund
1 parent 6dac8d2 commit 3e89f72

File tree

7 files changed

+120
-52
lines changed

7 files changed

+120
-52
lines changed

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "precompiled.hpp"
2525
#include "gc/shared/locationPrinter.hpp"
2626
#include "gc/z/zAddress.inline.hpp"
27+
#include "gc/z/zArray.inline.hpp"
2728
#include "gc/z/zGlobals.hpp"
2829
#include "gc/z/zHeap.inline.hpp"
2930
#include "gc/z/zHeapIterator.hpp"
@@ -220,6 +221,17 @@ void ZHeap::free_page(ZPage* page, bool reclaimed) {
220221
_page_allocator.free_page(page, reclaimed);
221222
}
222223

224+
void ZHeap::free_pages(const ZArray<ZPage*>* pages, bool reclaimed) {
225+
// Remove page table entries
226+
ZArrayIterator<ZPage*> iter(pages);
227+
for (ZPage* page; iter.next(&page);) {
228+
_page_table.remove(page);
229+
}
230+
231+
// Free pages
232+
_page_allocator.free_pages(pages, reclaimed);
233+
}
234+
223235
void ZHeap::flip_to_marked() {
224236
ZVerifyViewsFlip flip(&_page_allocator);
225237
ZAddress::flip_to_marked();
@@ -349,6 +361,16 @@ void ZHeap::process_non_strong_references() {
349361
_reference_processor.enqueue_references();
350362
}
351363

364+
void ZHeap::free_garbage_pages(ZRelocationSetSelector* selector, int bulk) {
365+
// Freeing garbage pages in bulk is an optimization to avoid grabbing
366+
// the page allocator lock, and trying to satisfy stalled allocations
367+
// too frequently.
368+
if (selector->should_free_garbage_pages(bulk)) {
369+
free_pages(selector->garbage_pages(), true /* reclaimed */);
370+
selector->clear_garbage_pages();
371+
}
372+
}
373+
352374
void ZHeap::select_relocation_set() {
353375
// Do not allow pages to be deleted
354376
_page_allocator.enable_deferred_delete();
@@ -369,11 +391,14 @@ void ZHeap::select_relocation_set() {
369391
// Register garbage page
370392
selector.register_garbage_page(page);
371393

372-
// Reclaim page immediately
373-
free_page(page, true /* reclaimed */);
394+
// Reclaim garbage pages in bulk
395+
free_garbage_pages(&selector, 64 /* bulk */);
374396
}
375397
}
376398

399+
// Reclaim remaining garbage pages
400+
free_garbage_pages(&selector, 0 /* bulk */);
401+
377402
// Allow pages to be deleted
378403
_page_allocator.disable_deferred_delete();
379404

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define SHARE_GC_Z_ZHEAP_HPP
2626

2727
#include "gc/z/zAllocationFlags.hpp"
28+
#include "gc/z/zArray.hpp"
2829
#include "gc/z/zForwardingTable.hpp"
2930
#include "gc/z/zMark.hpp"
3031
#include "gc/z/zObjectAllocator.hpp"
@@ -40,6 +41,7 @@
4041

4142
class ThreadClosure;
4243
class ZPage;
44+
class ZRelocationSetSelector;
4345

4446
class ZHeap {
4547
friend class VMStructs;
@@ -63,6 +65,8 @@ class ZHeap {
6365
void flip_to_marked();
6466
void flip_to_remapped();
6567

68+
void free_garbage_pages(ZRelocationSetSelector* selector, int bulk);
69+
6670
void out_of_memory();
6771

6872
public:
@@ -110,6 +114,7 @@ class ZHeap {
110114
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
111115
void undo_alloc_page(ZPage* page);
112116
void free_page(ZPage* page, bool reclaimed);
117+
void free_pages(const ZArray<ZPage*>* pages, bool reclaimed);
113118

114119
// Object allocation
115120
uintptr_t alloc_tlab(size_t size);

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "precompiled.hpp"
2525
#include "gc/shared/gcLogPrecious.hpp"
2626
#include "gc/shared/suspendibleThreadSet.hpp"
27+
#include "gc/z/zArray.inline.hpp"
2728
#include "gc/z/zCollectedHeap.hpp"
2829
#include "gc/z/zFuture.inline.hpp"
2930
#include "gc/z/zGlobals.hpp"
@@ -748,6 +749,19 @@ void ZPageAllocator::free_page(ZPage* page, bool reclaimed) {
748749
satisfy_stalled();
749750
}
750751

752+
void ZPageAllocator::free_pages(const ZArray<ZPage*>* pages, bool reclaimed) {
753+
ZLocker<ZLock> locker(&_lock);
754+
755+
// Free pages
756+
ZArrayIterator<ZPage*> iter(pages);
757+
for (ZPage* page; iter.next(&page);) {
758+
free_page_inner(page, reclaimed);
759+
}
760+
761+
// Try satisfy stalled allocations
762+
satisfy_stalled();
763+
}
764+
751765
size_t ZPageAllocator::uncommit(uint64_t* timeout) {
752766
// We need to join the suspendible thread set while manipulating capacity and
753767
// used, to make sure GC safepoints will have a consistent view. However, when

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define SHARE_GC_Z_ZPAGEALLOCATOR_HPP
2626

2727
#include "gc/z/zAllocationFlags.hpp"
28+
#include "gc/z/zArray.hpp"
2829
#include "gc/z/zList.hpp"
2930
#include "gc/z/zLock.hpp"
3031
#include "gc/z/zPageCache.hpp"
@@ -124,6 +125,7 @@ class ZPageAllocator {
124125

125126
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
126127
void free_page(ZPage* page, bool reclaimed);
128+
void free_pages(const ZArray<ZPage*>* pages, bool reclaimed);
127129

128130
void enable_deferred_delete() const;
129131
void disable_deferred_delete() const;

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

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,6 @@ ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name,
5454
_forwarding_entries(0),
5555
_stats() {}
5656

57-
void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
58-
const uint8_t type = page->type();
59-
const size_t size = page->size();
60-
const size_t live = page->live_bytes();
61-
const size_t garbage = size - live;
62-
63-
if (garbage > _fragmentation_limit) {
64-
_registered_pages.append(page);
65-
}
66-
67-
_stats._npages++;
68-
_stats._total += size;
69-
_stats._live += live;
70-
_stats._garbage += garbage;
71-
}
72-
73-
void ZRelocationSetSelectorGroup::register_garbage_page(ZPage* page) {
74-
const size_t size = page->size();
75-
76-
_stats._npages++;
77-
_stats._total += size;
78-
_stats._garbage += size;
79-
_stats._empty += size;
80-
}
81-
8257
bool ZRelocationSetSelectorGroup::is_disabled() {
8358
// Medium pages are disabled when their page size is zero
8459
return _page_type == ZPageTypeMedium && _page_size == 0;
@@ -205,31 +180,8 @@ void ZRelocationSetSelectorGroup::select() {
205180
ZRelocationSetSelector::ZRelocationSetSelector() :
206181
_small("Small", ZPageTypeSmall, ZPageSizeSmall, ZObjectSizeLimitSmall),
207182
_medium("Medium", ZPageTypeMedium, ZPageSizeMedium, ZObjectSizeLimitMedium),
208-
_large("Large", ZPageTypeLarge, 0 /* page_size */, 0 /* object_size_limit */) {}
209-
210-
void ZRelocationSetSelector::register_live_page(ZPage* page) {
211-
const uint8_t type = page->type();
212-
213-
if (type == ZPageTypeSmall) {
214-
_small.register_live_page(page);
215-
} else if (type == ZPageTypeMedium) {
216-
_medium.register_live_page(page);
217-
} else {
218-
_large.register_live_page(page);
219-
}
220-
}
221-
222-
void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
223-
const uint8_t type = page->type();
224-
225-
if (type == ZPageTypeSmall) {
226-
_small.register_garbage_page(page);
227-
} else if (type == ZPageTypeMedium) {
228-
_medium.register_garbage_page(page);
229-
} else {
230-
_large.register_garbage_page(page);
231-
}
232-
}
183+
_large("Large", ZPageTypeLarge, 0 /* page_size */, 0 /* object_size_limit */),
184+
_garbage_pages() {}
233185

234186
void ZRelocationSetSelector::select() {
235187
// Select pages to relocate. The resulting relocation set will be

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class ZRelocationSetSelector : public StackObj {
104104
ZRelocationSetSelectorGroup _small;
105105
ZRelocationSetSelectorGroup _medium;
106106
ZRelocationSetSelectorGroup _large;
107+
ZArray<ZPage*> _garbage_pages;
107108

108109
size_t total() const;
109110
size_t empty() const;
@@ -116,6 +117,10 @@ class ZRelocationSetSelector : public StackObj {
116117
void register_live_page(ZPage* page);
117118
void register_garbage_page(ZPage* page);
118119

120+
bool should_free_garbage_pages(int bulk) const;
121+
const ZArray<ZPage*>* garbage_pages() const;
122+
void clear_garbage_pages();
123+
119124
void select();
120125

121126
const ZArray<ZPage*>* small() const;

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#ifndef SHARE_GC_Z_ZRELOCATIONSETSELECTOR_INLINE_HPP
2525
#define SHARE_GC_Z_ZRELOCATIONSETSELECTOR_INLINE_HPP
2626

27+
#include "gc/z/zArray.inline.hpp"
28+
#include "gc/z/zPage.inline.hpp"
2729
#include "gc/z/zRelocationSetSelector.hpp"
2830

2931
inline size_t ZRelocationSetSelectorGroupStats::npages() const {
@@ -66,6 +68,31 @@ inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::larg
6668
return _large;
6769
}
6870

71+
inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
72+
const uint8_t type = page->type();
73+
const size_t size = page->size();
74+
const size_t live = page->live_bytes();
75+
const size_t garbage = size - live;
76+
77+
if (garbage > _fragmentation_limit) {
78+
_registered_pages.append(page);
79+
}
80+
81+
_stats._npages++;
82+
_stats._total += size;
83+
_stats._live += live;
84+
_stats._garbage += garbage;
85+
}
86+
87+
inline void ZRelocationSetSelectorGroup::register_garbage_page(ZPage* page) {
88+
const size_t size = page->size();
89+
90+
_stats._npages++;
91+
_stats._total += size;
92+
_stats._garbage += size;
93+
_stats._empty += size;
94+
}
95+
6996
inline const ZArray<ZPage*>* ZRelocationSetSelectorGroup::selected() const {
7097
return &_registered_pages;
7198
}
@@ -78,6 +105,44 @@ inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stat
78105
return _stats;
79106
}
80107

108+
inline void ZRelocationSetSelector::register_live_page(ZPage* page) {
109+
const uint8_t type = page->type();
110+
111+
if (type == ZPageTypeSmall) {
112+
_small.register_live_page(page);
113+
} else if (type == ZPageTypeMedium) {
114+
_medium.register_live_page(page);
115+
} else {
116+
_large.register_live_page(page);
117+
}
118+
}
119+
120+
inline void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
121+
const uint8_t type = page->type();
122+
123+
if (type == ZPageTypeSmall) {
124+
_small.register_garbage_page(page);
125+
} else if (type == ZPageTypeMedium) {
126+
_medium.register_garbage_page(page);
127+
} else {
128+
_large.register_garbage_page(page);
129+
}
130+
131+
_garbage_pages.append(page);
132+
}
133+
134+
inline bool ZRelocationSetSelector::should_free_garbage_pages(int bulk) const {
135+
return _garbage_pages.length() >= bulk && _garbage_pages.is_nonempty();
136+
}
137+
138+
inline const ZArray<ZPage*>* ZRelocationSetSelector::garbage_pages() const {
139+
return &_garbage_pages;
140+
}
141+
142+
inline void ZRelocationSetSelector::clear_garbage_pages() {
143+
return _garbage_pages.clear();
144+
}
145+
81146
inline size_t ZRelocationSetSelector::total() const {
82147
return _small.stats().total() + _medium.stats().total() + _large.stats().total();
83148
}

0 commit comments

Comments
 (0)