OpenJDK / jdk / jdk
changeset 57197:79fba633d07f
8234543: ZGC: Parallel pre-touch
Reviewed-by: eosterlund, stefank
line wrap: on
line diff
--- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -148,7 +148,7 @@ os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); } -void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const { +void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { const size_t nsegments = pmem.nsegments(); size_t size = 0; @@ -159,11 +159,6 @@ _file.map(segment_addr, segment.size(), segment.start()); size += segment.size(); } - - // Pre-touch memory - if (pretouch) { - pretouch_view(addr, size); - } } void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { @@ -175,15 +170,27 @@ return ZAddress::marked0(offset); } +void ZPhysicalMemoryBacking::pretouch(uintptr_t offset, size_t size) const { + if (ZVerifyViews) { + // Pre-touch good view + pretouch_view(ZAddress::good(offset), size); + } else { + // Pre-touch all views + pretouch_view(ZAddress::marked0(offset), size); + pretouch_view(ZAddress::marked1(offset), size); + pretouch_view(ZAddress::remapped(offset), size); + } +} + void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { if (ZVerifyViews) { // Map good view - map_view(pmem, ZAddress::good(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::good(offset)); } else { // Map all views - map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::marked0(offset)); + map_view(pmem, ZAddress::marked1(offset)); + map_view(pmem, ZAddress::remapped(offset)); } } @@ -202,7 +209,7 @@ void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { // Map good view assert(ZVerifyViews, "Should be enabled"); - map_view(pmem, ZAddress::good(offset), false /* pretouch */); + map_view(pmem, ZAddress::good(offset)); } void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
--- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.hpp Tue Dec 03 13:51:29 2019 +0100 @@ -36,7 +36,7 @@ ZMemoryManager _uncommitted; void pretouch_view(uintptr_t addr, size_t size) const; - void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const; + void map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; public: @@ -53,6 +53,8 @@ uintptr_t nmt_address(uintptr_t offset) const; + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
--- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -249,7 +249,7 @@ os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); } -void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const { +void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { const size_t nsegments = pmem.nsegments(); size_t size = 0; @@ -273,11 +273,6 @@ // NUMA interleave memory before touching it ZNUMA::memory_interleave(addr, size); - - // Pre-touch memory - if (pretouch) { - pretouch_view(addr, size); - } } void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { @@ -296,15 +291,27 @@ return ZAddress::marked0(offset); } +void ZPhysicalMemoryBacking::pretouch(uintptr_t offset, size_t size) const { + if (ZVerifyViews) { + // Pre-touch good view + pretouch_view(ZAddress::good(offset), size); + } else { + // Pre-touch all views + pretouch_view(ZAddress::marked0(offset), size); + pretouch_view(ZAddress::marked1(offset), size); + pretouch_view(ZAddress::remapped(offset), size); + } +} + void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { if (ZVerifyViews) { // Map good view - map_view(pmem, ZAddress::good(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::good(offset)); } else { // Map all views - map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::marked0(offset)); + map_view(pmem, ZAddress::marked1(offset)); + map_view(pmem, ZAddress::remapped(offset)); } } @@ -323,7 +330,7 @@ void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { // Map good view assert(ZVerifyViews, "Should be enabled"); - map_view(pmem, ZAddress::good(offset), false /* pretouch */); + map_view(pmem, ZAddress::good(offset)); } void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
--- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp Tue Dec 03 13:51:29 2019 +0100 @@ -43,7 +43,7 @@ void advise_view(uintptr_t addr, size_t size, int advice) const; void pretouch_view(uintptr_t addr, size_t size) const; - void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const; + void map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; public: @@ -60,6 +60,8 @@ uintptr_t nmt_address(uintptr_t offset) const; + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
--- a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -149,7 +149,7 @@ os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); } -void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const { +void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { const size_t nsegments = pmem.nsegments(); size_t size = 0; @@ -159,11 +159,6 @@ _file.map(addr + size, segment.size(), segment.start()); size += segment.size(); } - - // Pre-touch memory - if (pretouch) { - pretouch_view(addr, size); - } } void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { @@ -175,15 +170,27 @@ return ZAddress::marked0(offset); } +void ZPhysicalMemoryBacking::pretouch(uintptr_t offset, size_t size) const { + if (ZVerifyViews) { + // Pre-touch good view + pretouch_view(ZAddress::good(offset), size); + } else { + // Pre-touch all views + pretouch_view(ZAddress::marked0(offset), size); + pretouch_view(ZAddress::marked1(offset), size); + pretouch_view(ZAddress::remapped(offset), size); + } +} + void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { if (ZVerifyViews) { // Map good view - map_view(pmem, ZAddress::good(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::good(offset)); } else { // Map all views - map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::marked0(offset)); + map_view(pmem, ZAddress::marked1(offset)); + map_view(pmem, ZAddress::remapped(offset)); } } @@ -202,7 +209,7 @@ void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { // Map good view assert(ZVerifyViews, "Should be enabled"); - map_view(pmem, ZAddress::good(offset), false /* pretouch */); + map_view(pmem, ZAddress::good(offset)); } void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const {
--- a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp Tue Dec 03 13:51:29 2019 +0100 @@ -36,7 +36,7 @@ ZMemoryManager _uncommitted; void pretouch_view(uintptr_t addr, size_t size) const; - void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const; + void map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; public: @@ -53,6 +53,8 @@ uintptr_t nmt_address(uintptr_t offset) const; + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
--- a/src/hotspot/share/gc/z/zHeap.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zHeap.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -57,7 +57,7 @@ ZHeap::ZHeap() : _workers(), _object_allocator(), - _page_allocator(heap_min_size(), heap_initial_size(), heap_max_size(), heap_max_reserve_size()), + _page_allocator(&_workers, heap_min_size(), heap_initial_size(), heap_max_size(), heap_max_reserve_size()), _page_table(), _forwarding_table(), _mark(&_workers, &_page_table),
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -33,7 +33,9 @@ #include "gc/z/zPageCache.inline.hpp" #include "gc/z/zSafeDelete.inline.hpp" #include "gc/z/zStat.hpp" +#include "gc/z/zTask.hpp" #include "gc/z/zTracer.inline.hpp" +#include "gc/z/zWorkers.hpp" #include "runtime/globals.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" @@ -95,7 +97,8 @@ ZPage* const ZPageAllocator::gc_marker = (ZPage*)-1; -ZPageAllocator::ZPageAllocator(size_t min_capacity, +ZPageAllocator::ZPageAllocator(ZWorkers* workers, + size_t min_capacity, size_t initial_capacity, size_t max_capacity, size_t max_reserve) : @@ -150,13 +153,42 @@ } // Pre-map initial capacity - prime_cache(initial_capacity); + prime_cache(workers, initial_capacity); // Successfully initialized _initialized = true; } -void ZPageAllocator::prime_cache(size_t size) { +class ZPreTouchTask : public ZTask { +private: + const ZPhysicalMemoryManager* const _physical; + volatile uintptr_t _start; + const uintptr_t _end; + +public: + ZPreTouchTask(const ZPhysicalMemoryManager* physical, uintptr_t start, uintptr_t end) : + ZTask("ZPreTouchTask"), + _physical(physical), + _start(start), + _end(end) {} + + virtual void work() { + for (;;) { + // Get granule offset + const size_t size = ZGranuleSize; + const uintptr_t offset = Atomic::add(&_start, size) - size; + if (offset >= _end) { + // Done + break; + } + + // Pre-touch granule + _physical->pretouch(offset, size); + } + } +}; + +void ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) { // Allocate physical memory const ZPhysicalMemory pmem = _physical.alloc(size); guarantee(!pmem.is_null(), "Invalid size"); @@ -172,6 +204,12 @@ map_page(page); page->set_pre_mapped(); + if (AlwaysPreTouch) { + // Pre-touch page + ZPreTouchTask task(&_physical, page->start(), page->end()); + workers->run_parallel(&task); + } + // Add page to cache page->set_last_used(); _cache.free_page(page);
--- a/src/hotspot/share/gc/z/zPageAllocator.hpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zPageAllocator.hpp Tue Dec 03 13:51:29 2019 +0100 @@ -34,6 +34,7 @@ #include "memory/allocation.hpp" class ZPageAllocRequest; +class ZWorkers; class ZPageAllocator { friend class VMStructs; @@ -61,7 +62,7 @@ static ZPage* const gc_marker; - void prime_cache(size_t size); + void prime_cache(ZWorkers* workers, size_t size); void increase_used(size_t size, bool relocation); void decrease_used(size_t size, bool reclaimed); @@ -86,7 +87,8 @@ void satisfy_alloc_queue(); public: - ZPageAllocator(size_t min_capacity, + ZPageAllocator(ZWorkers* workers, + size_t min_capacity, size_t initial_capacity, size_t max_capacity, size_t max_reserve);
--- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -173,6 +173,10 @@ _backing.free(pmem); } +void ZPhysicalMemoryManager::pretouch(uintptr_t offset, size_t size) const { + _backing.pretouch(offset, size); +} + void ZPhysicalMemoryManager::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { _backing.map(pmem, offset); nmt_commit(pmem, offset);
--- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp Tue Dec 03 13:51:29 2019 +0100 @@ -82,6 +82,8 @@ ZPhysicalMemory alloc(size_t size); void free(const ZPhysicalMemory& pmem); + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const;
--- a/src/hotspot/share/gc/z/zWorkers.cpp Tue Dec 03 08:35:21 2019 -0400 +++ b/src/hotspot/share/gc/z/zWorkers.cpp Tue Dec 03 13:51:29 2019 +0100 @@ -100,7 +100,6 @@ } void ZWorkers::run_parallel(ZTask* task) { - assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint"); run(task, nparallel()); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/gc/z/TestAlwaysPreTouch.java Tue Dec 03 13:51:29 2019 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.z; + +/* + * @test TestAlwaysPreTouch + * @requires vm.gc.Z & !vm.graal.enabled + * @summary Test ZGC parallel pre-touch + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* -XX:-AlwaysPreTouch -Xms128M -Xmx128M gc.z.TestAlwaysPreTouch + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* -XX:+AlwaysPreTouch -XX:ParallelGCThreads=1 -Xms2M -Xmx128M gc.z.TestAlwaysPreTouch + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* -XX:+AlwaysPreTouch -XX:ParallelGCThreads=8 -Xms2M -Xmx128M gc.z.TestAlwaysPreTouch + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* -XX:+AlwaysPreTouch -XX:ParallelGCThreads=1 -Xms128M -Xmx128M gc.z.TestAlwaysPreTouch + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* -XX:+AlwaysPreTouch -XX:ParallelGCThreads=8 -Xms128M -Xmx128M gc.z.TestAlwaysPreTouch + */ + +public class TestAlwaysPreTouch { + public static void main(String[] args) throws Exception { + System.out.println("Success"); + } +}