8202842: G1 footprint regressions in jdk11+10
Summary: Lazily initialize G1FromCardCache to save on startup footprint if AlwaysPretouch is disabled.
Reviewed-by: sjohanss, redestad
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Mon May 28 11:13:21 2018 +0200
@@ -1611,6 +1611,9 @@
const uint max_region_idx = (1U << (sizeof(RegionIdx_t)*BitsPerByte-1)) - 1;
guarantee((max_regions() - 1) <= max_region_idx, "too many regions");
+ // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not
+ // start within the first card.
+ guarantee(g1_rs.base() >= (char*)G1CardTable::card_size, "Java heap must not start within the first card.");
// Also create a G1 rem set.
_g1_rem_set = new G1RemSet(this, _card_table, _hot_card_cache);
_g1_rem_set->initialize(max_capacity(), max_regions());
--- a/src/hotspot/share/gc/g1/g1FromCardCache.cpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FromCardCache.cpp Mon May 28 11:13:21 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -47,7 +47,9 @@
num_par_rem_sets,
&_static_mem_size);
- invalidate(0, _max_regions);
+ if (AlwaysPreTouch) {
+ invalidate(0, _max_regions);
+ }
}
void G1FromCardCache::invalidate(uint start_idx, size_t new_num_regions) {
--- a/src/hotspot/share/gc/g1/g1FromCardCache.hpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FromCardCache.hpp Mon May 28 11:13:21 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -31,7 +31,7 @@
// G1FromCardCache remembers the most recently processed card on the heap on
// a per-region and per-thread basis.
class G1FromCardCache : public AllStatic {
- private:
+private:
// Array of card indices. Indexed by heap region (rows) and thread (columns) to minimize
// thread contention.
// This order minimizes the time to clear all entries for a given region during region
@@ -49,9 +49,12 @@
}
#endif
- public:
- static const uintptr_t InvalidCard = UINTPTR_MAX;
+ // This card index indicates "no card for that entry" yet. This allows us to use the OS
+ // lazy backing of memory with zero-filled pages to avoid initial actual memory use.
+ // This means that the heap must not contain card zero.
+ static const uintptr_t InvalidCard = 0;
+public:
static void clear(uint region_idx);
// Returns true if the given card is in the cache at the given location, or
--- a/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1RegionMarkStatsCache.cpp Mon May 28 11:13:21 2018 +0200
@@ -36,9 +36,6 @@
guarantee(is_power_of_2(num_cache_entries),
"Number of cache entries must be power of two, but is %u", num_cache_entries);
_cache = NEW_C_HEAP_ARRAY(G1RegionMarkStatsCacheEntry, _num_cache_entries, mtGC);
- for (uint i = 0; i < _num_cache_entries; i++) {
- _cache[i].clear();
- }
_num_cache_entries_mask = _num_cache_entries - 1;
}
--- a/src/hotspot/share/memory/padded.hpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/memory/padded.hpp Mon May 28 11:13:21 2018 +0200
@@ -104,6 +104,8 @@
public:
// Creates an aligned padded 2D array.
// The memory cannot be deleted since the raw memory chunk is not returned.
+ // Always uses mmap to reserve memory. Only the first few pages with the index to
+ // the rows are touched. Allocation size should be "large" to cover page overhead.
static T** create_unfreeable(uint rows, uint columns, size_t* allocation_size = NULL);
};
--- a/src/hotspot/share/memory/padded.inline.hpp Mon May 28 09:59:11 2018 +0200
+++ b/src/hotspot/share/memory/padded.inline.hpp Mon May 28 11:13:21 2018 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -62,9 +62,8 @@
size_t total_size = table_size + rows * row_size + alignment;
// Allocate a chunk of memory large enough to allow alignment of the chunk.
- void* chunk = AllocateHeap(total_size, flags);
+ void* chunk = MmapArrayAllocator<uint8_t>::allocate(total_size, flags);
// Clear the allocated memory.
- memset(chunk, 0, total_size);
// Align the chunk of memory.
T** result = (T**)align_up(chunk, alignment);
void* data_start = (void*)((uintptr_t)result + table_size);