Skip to content

Commit 9359ff0

Browse files
amitdpawarThomas Schatzl
authored and
Thomas Schatzl
committedOct 15, 2020
8252221: Use multiple workers for Parallel GC pre-touching
Reviewed-by: kbarrett, tschatzl
1 parent f44fc6d commit 9359ff0

10 files changed

+191
-75
lines changed
 

‎src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.cpp

+4-49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2020, 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
@@ -24,6 +24,7 @@
2424

2525
#include "precompiled.hpp"
2626
#include "gc/g1/g1PageBasedVirtualSpace.hpp"
27+
#include "gc/shared/pretouchTask.hpp"
2728
#include "gc/shared/workgroup.hpp"
2829
#include "oops/markWord.hpp"
2930
#include "oops/oop.inline.hpp"
@@ -234,56 +235,10 @@ void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages)
234235
_committed.clear_range(start_page, end_page);
235236
}
236237

237-
class G1PretouchTask : public AbstractGangTask {
238-
private:
239-
char* volatile _cur_addr;
240-
char* const _start_addr;
241-
char* const _end_addr;
242-
size_t _page_size;
243-
public:
244-
G1PretouchTask(char* start_address, char* end_address, size_t page_size) :
245-
AbstractGangTask("G1 PreTouch"),
246-
_cur_addr(start_address),
247-
_start_addr(start_address),
248-
_end_addr(end_address),
249-
_page_size(0) {
250-
#ifdef LINUX
251-
_page_size = UseTransparentHugePages ? (size_t)os::vm_page_size(): page_size;
252-
#else
253-
_page_size = page_size;
254-
#endif
255-
}
256-
257-
virtual void work(uint worker_id) {
258-
size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
259-
while (true) {
260-
char* touch_addr = Atomic::fetch_and_add(&_cur_addr, actual_chunk_size);
261-
if (touch_addr < _start_addr || touch_addr >= _end_addr) {
262-
break;
263-
}
264-
char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
265-
os::pretouch_memory(touch_addr, end_addr, _page_size);
266-
}
267-
}
268-
269-
static size_t chunk_size() { return PreTouchParallelChunkSize; }
270-
};
271-
272238
void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
273-
G1PretouchTask cl(page_start(start_page), bounded_end_addr(start_page + size_in_pages), _page_size);
274-
275-
if (pretouch_gang != NULL) {
276-
size_t num_chunks = MAX2((size_t)1, size_in_pages * _page_size / MAX2(G1PretouchTask::chunk_size(), _page_size));
277239

278-
uint num_workers = MIN2((uint)num_chunks, pretouch_gang->total_workers());
279-
log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
280-
cl.name(), num_workers, num_chunks, size_in_pages * _page_size);
281-
pretouch_gang->run_task(&cl, num_workers);
282-
} else {
283-
log_debug(gc, heap)("Running %s pre-touching " SIZE_FORMAT "B.",
284-
cl.name(), size_in_pages * _page_size);
285-
cl.work(0);
286-
}
240+
PretouchTask::pretouch("G1 PreTouch", page_start(start_page), bounded_end_addr(start_page + size_in_pages),
241+
_page_size, pretouch_gang);
287242
}
288243

289244
bool G1PageBasedVirtualSpace::contains(const void* p) const {

‎src/hotspot/share/gc/parallel/mutableNUMASpace.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "gc/parallel/mutableNUMASpace.hpp"
2727
#include "gc/shared/collectedHeap.hpp"
2828
#include "gc/shared/spaceDecorator.hpp"
29+
#include "gc/shared/workgroup.hpp"
2930
#include "memory/allocation.inline.hpp"
3031
#include "oops/oop.inline.hpp"
3132
#include "runtime/atomic.hpp"
@@ -572,7 +573,8 @@ void MutableNUMASpace::merge_regions(MemRegion new_region, MemRegion* intersecti
572573
void MutableNUMASpace::initialize(MemRegion mr,
573574
bool clear_space,
574575
bool mangle_space,
575-
bool setup_pages) {
576+
bool setup_pages,
577+
WorkGang* pretouch_gang) {
576578
assert(clear_space, "Reallocation will destroy data!");
577579
assert(lgrp_spaces()->length() > 0, "There should be at least one space");
578580

‎src/hotspot/share/gc/parallel/mutableNUMASpace.hpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2006, 2020, 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
@@ -195,7 +195,11 @@ class MutableNUMASpace : public MutableSpace {
195195
MutableNUMASpace(size_t alignment);
196196
virtual ~MutableNUMASpace();
197197
// Space initialization.
198-
virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space, bool setup_pages = SetupPages);
198+
virtual void initialize(MemRegion mr,
199+
bool clear_space,
200+
bool mangle_space,
201+
bool setup_pages = SetupPages,
202+
WorkGang* pretouch_gang = NULL);
199203
// Update space layout if necessary. Do all adaptive resizing job.
200204
virtual void update();
201205
// Update allocation rate averages.

‎src/hotspot/share/gc/parallel/mutableSpace.cpp

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2020, 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
@@ -24,6 +24,7 @@
2424

2525
#include "precompiled.hpp"
2626
#include "gc/parallel/mutableSpace.hpp"
27+
#include "gc/shared/pretouchTask.hpp"
2728
#include "gc/shared/spaceDecorator.inline.hpp"
2829
#include "memory/iterator.inline.hpp"
2930
#include "memory/universe.hpp"
@@ -60,14 +61,11 @@ void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) {
6061
}
6162
}
6263

63-
void MutableSpace::pretouch_pages(MemRegion mr) {
64-
os::pretouch_memory(mr.start(), mr.end());
65-
}
66-
6764
void MutableSpace::initialize(MemRegion mr,
6865
bool clear_space,
6966
bool mangle_space,
70-
bool setup_pages) {
67+
bool setup_pages,
68+
WorkGang* pretouch_gang) {
7169

7270
assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()),
7371
"invalid space boundaries");
@@ -114,8 +112,13 @@ void MutableSpace::initialize(MemRegion mr,
114112
}
115113

116114
if (AlwaysPreTouch) {
117-
pretouch_pages(head);
118-
pretouch_pages(tail);
115+
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
116+
117+
PretouchTask::pretouch("ParallelGC PreTouch head", (char*)head.start(), (char*)head.end(),
118+
page_size, pretouch_gang);
119+
120+
PretouchTask::pretouch("ParallelGC PreTouch tail", (char*)tail.start(), (char*)tail.end(),
121+
page_size, pretouch_gang);
119122
}
120123

121124
// Remember where we stopped so that we can continue later.

‎src/hotspot/share/gc/parallel/mutableSpace.hpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2001, 2020, 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
@@ -29,6 +29,8 @@
2929
#include "memory/memRegion.hpp"
3030
#include "utilities/copy.hpp"
3131

32+
class WorkGang;
33+
3234
// A MutableSpace is a subtype of ImmutableSpace that supports the
3335
// concept of allocation. This includes the concepts that a space may
3436
// be only partially full, and the query methods that go with such
@@ -56,7 +58,6 @@ class MutableSpace: public ImmutableSpace {
5658
MutableSpaceMangler* mangler() { return _mangler; }
5759

5860
void numa_setup_pages(MemRegion mr, bool clear_space);
59-
void pretouch_pages(MemRegion mr);
6061

6162
void set_last_setup_region(MemRegion mr) { _last_setup_region = mr; }
6263
MemRegion last_setup_region() const { return _last_setup_region; }
@@ -87,7 +88,8 @@ class MutableSpace: public ImmutableSpace {
8788
virtual void initialize(MemRegion mr,
8889
bool clear_space,
8990
bool mangle_space,
90-
bool setup_pages = SetupPages);
91+
bool setup_pages = SetupPages,
92+
WorkGang* pretouch_gang = NULL);
9193

9294
virtual void clear(bool mangle_space);
9395
// Does the usual initialization but optionally resets top to bottom.

‎src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ jint ParallelScavengeHeap::initialize() {
8888
ReservedSpace young_rs = heap_rs.last_part(MaxOldSize);
8989
assert(young_rs.size() == MaxNewSize, "Didn't reserve all of the heap");
9090

91+
// Set up WorkGang
92+
_workers.initialize_workers();
93+
9194
// Create and initialize the generations.
9295
_young_gen = new PSYoungGen(
9396
young_rs,
@@ -132,9 +135,6 @@ jint ParallelScavengeHeap::initialize() {
132135
return JNI_ENOMEM;
133136
}
134137

135-
// Set up WorkGang
136-
_workers.initialize_workers();
137-
138138
GCInitLogger::print();
139139

140140
return JNI_OK;

‎src/hotspot/share/gc/parallel/psOldGen.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) {
131131
_object_space = new MutableSpace(virtual_space()->alignment());
132132
object_space()->initialize(cmr,
133133
SpaceDecorator::Clear,
134-
SpaceDecorator::Mangle);
134+
SpaceDecorator::Mangle,
135+
MutableSpace::SetupPages,
136+
&ParallelScavengeHeap::heap()->workers());
135137

136138
// Update the start_array
137139
start_array()->set_covered_region(cmr);
@@ -351,10 +353,15 @@ void PSOldGen::post_resize() {
351353
start_array()->set_covered_region(new_memregion);
352354
ParallelScavengeHeap::heap()->card_table()->resize_covered_region(new_memregion);
353355

356+
WorkGang* workers = Thread::current()->is_VM_thread() ?
357+
&ParallelScavengeHeap::heap()->workers() : NULL;
358+
354359
// ALWAYS do this last!!
355360
object_space()->initialize(new_memregion,
356361
SpaceDecorator::DontClear,
357-
SpaceDecorator::DontMangle);
362+
SpaceDecorator::DontMangle,
363+
MutableSpace::SetupPages,
364+
workers);
358365

359366
assert(new_word_size == heap_word_size(object_space()->capacity_in_bytes()),
360367
"Sanity");

‎src/hotspot/share/gc/parallel/psYoungGen.cpp

+20-7
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,10 @@ void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) {
189189
MemRegion to_mr ((HeapWord*)to_start, (HeapWord*)from_start);
190190
MemRegion from_mr((HeapWord*)from_start, (HeapWord*)from_end);
191191

192-
eden_space()->initialize(eden_mr, true, ZapUnusedHeapArea);
193-
to_space()->initialize(to_mr , true, ZapUnusedHeapArea);
194-
from_space()->initialize(from_mr, true, ZapUnusedHeapArea);
192+
WorkGang& pretouch_workers = ParallelScavengeHeap::heap()->workers();
193+
eden_space()->initialize(eden_mr, true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
194+
to_space()->initialize(to_mr , true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
195+
from_space()->initialize(from_mr, true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
195196
}
196197

197198
#ifndef PRODUCT
@@ -636,17 +637,26 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size,
636637
from_space()->check_mangled_unused_area(limit);
637638
to_space()->check_mangled_unused_area(limit);
638639
}
640+
641+
WorkGang* workers = &ParallelScavengeHeap::heap()->workers();
642+
639643
// When an existing space is being initialized, it is not
640644
// mangled because the space has been previously mangled.
641645
eden_space()->initialize(edenMR,
642646
SpaceDecorator::Clear,
643-
SpaceDecorator::DontMangle);
647+
SpaceDecorator::DontMangle,
648+
MutableSpace::SetupPages,
649+
workers);
644650
to_space()->initialize(toMR,
645651
SpaceDecorator::Clear,
646-
SpaceDecorator::DontMangle);
652+
SpaceDecorator::DontMangle,
653+
MutableSpace::SetupPages,
654+
workers);
647655
from_space()->initialize(fromMR,
648656
SpaceDecorator::DontClear,
649-
SpaceDecorator::DontMangle);
657+
SpaceDecorator::DontMangle,
658+
MutableSpace::SetupPages,
659+
workers);
650660

651661
assert(from_space()->top() == old_from_top, "from top changed!");
652662

@@ -783,9 +793,12 @@ void PSYoungGen::reset_survivors_after_shrink() {
783793
// Was there a shrink of the survivor space?
784794
if (new_end < space_shrinking->end()) {
785795
MemRegion mr(space_shrinking->bottom(), new_end);
796+
786797
space_shrinking->initialize(mr,
787798
SpaceDecorator::DontClear,
788-
SpaceDecorator::Mangle);
799+
SpaceDecorator::Mangle,
800+
MutableSpace::SetupPages,
801+
&ParallelScavengeHeap::heap()->workers());
789802
}
790803
}
791804

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
#include "precompiled.hpp"
26+
#include "gc/shared/pretouchTask.hpp"
27+
#include "runtime/atomic.hpp"
28+
#include "runtime/globals.hpp"
29+
#include "runtime/os.hpp"
30+
31+
PretouchTask::PretouchTask(const char* task_name, char* start_address, char* end_address, size_t page_size) :
32+
AbstractGangTask(task_name),
33+
_cur_addr(start_address),
34+
_start_addr(start_address),
35+
_end_addr(end_address),
36+
_page_size(0) {
37+
#ifdef LINUX
38+
_page_size = UseTransparentHugePages ? (size_t)os::vm_page_size(): page_size;
39+
#else
40+
_page_size = page_size;
41+
#endif
42+
}
43+
44+
size_t PretouchTask::chunk_size() {
45+
return PreTouchParallelChunkSize;
46+
}
47+
48+
void PretouchTask::work(uint worker_id) {
49+
size_t const actual_chunk_size = MAX2(chunk_size(), _page_size);
50+
51+
while (true) {
52+
char* touch_addr = Atomic::fetch_and_add(&_cur_addr, actual_chunk_size);
53+
if (touch_addr < _start_addr || touch_addr >= _end_addr) {
54+
break;
55+
}
56+
57+
char* end_addr = touch_addr + MIN2(actual_chunk_size, pointer_delta(_end_addr, touch_addr, sizeof(char)));
58+
59+
os::pretouch_memory(touch_addr, end_addr, _page_size);
60+
}
61+
}
62+
63+
void PretouchTask::pretouch(const char* task_name, char* start_address, char* end_address,
64+
size_t page_size, WorkGang* pretouch_gang) {
65+
PretouchTask task(task_name, start_address, end_address, page_size);
66+
size_t total_bytes = pointer_delta(end_address, start_address, sizeof(char));
67+
68+
if (pretouch_gang != NULL) {
69+
size_t num_chunks = MAX2((size_t)1, total_bytes / MAX2(PretouchTask::chunk_size(), page_size));
70+
71+
uint num_workers = MIN2((uint)num_chunks, pretouch_gang->total_workers());
72+
log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
73+
task.name(), num_workers, num_chunks, total_bytes);
74+
75+
pretouch_gang->run_task(&task, num_workers);
76+
} else {
77+
log_debug(gc, heap)("Running %s pre-touching " SIZE_FORMAT "B.",
78+
task.name(), total_bytes);
79+
task.work(0);
80+
}
81+
}
82+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
#ifndef SHARE_GC_SHARED_PRETOUCH_HPP
26+
#define SHARE_GC_SHARED_PRETOUCH_HPP
27+
28+
#include "gc/shared/workgroup.hpp"
29+
30+
class PretouchTask : public AbstractGangTask {
31+
char* volatile _cur_addr;
32+
char* const _start_addr;
33+
char* const _end_addr;
34+
size_t _page_size;
35+
36+
public:
37+
PretouchTask(const char* task_name, char* start_address, char* end_address, size_t page_size);
38+
39+
virtual void work(uint worker_id);
40+
41+
static size_t chunk_size();
42+
43+
static void pretouch(const char* task_name, char* start_address, char* end_address,
44+
size_t page_size, WorkGang* pretouch_gang);
45+
46+
};
47+
48+
#endif // SHARE_GC_SHARED_PRETOUCH_HPP

0 commit comments

Comments
 (0)
Please sign in to comment.