Skip to content

Commit 526f543

Browse files
committed
8353184: ZGC: Simplify and correct tlab_used() tracking
Reviewed-by: stefank, aboldtch
1 parent 03dca03 commit 526f543

File tree

12 files changed

+186
-47
lines changed

12 files changed

+186
-47
lines changed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ ZAllocatorEden::ZAllocatorEden()
3939
ZAllocator::_eden = this;
4040
}
4141

42-
size_t ZAllocatorEden::tlab_used() const {
43-
return _object_allocator.used();
44-
}
45-
4642
size_t ZAllocatorEden::remaining() const {
4743
return _object_allocator.remaining();
4844
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class ZAllocatorEden : public ZAllocator {
6262
zaddress alloc_object(size_t size);
6363

6464
// Statistics
65-
size_t tlab_used() const;
6665
size_t remaining() const;
6766
};
6867

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ void ZArguments::initialize() {
143143
FLAG_SET_ERGO_IF_DEFAULT(ZCollectionIntervalMajor, ZCollectionInterval);
144144
}
145145

146+
// Set an initial TLAB size to avoid depending on the current capacity
147+
if (FLAG_IS_DEFAULT(TLABSize)) {
148+
FLAG_SET_DEFAULT(TLABSize, 256*K);
149+
}
150+
146151
// Set medium page size here because MaxTenuringThreshold may use it.
147152
ZHeuristics::set_medium_page_size();
148153

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ size_t ZCollectedHeap::tlab_used(Thread* ignored) const {
238238
}
239239

240240
size_t ZCollectedHeap::max_tlab_size() const {
241-
return _heap.max_tlab_size();
241+
return _heap.max_tlab_size() / HeapWordSize;
242242
}
243243

244244
size_t ZCollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,9 @@ void ZGenerationYoung::mark_start() {
837837
// Change good colors
838838
flip_mark_start();
839839

840+
// Reset TLAB usage
841+
ZHeap::heap()->reset_tlab_used();
842+
840843
// Retire allocating pages
841844
ZAllocator::eden()->retire_pages();
842845
for (ZPageAge i = ZPageAge::survivor1; i <= ZPageAge::survivor14; i = static_cast<ZPageAge>(static_cast<uint>(i) + 1)) {

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ ZHeap::ZHeap()
6262
_serviceability(InitialHeapSize, min_capacity(), max_capacity()),
6363
_old(&_page_table, &_page_allocator),
6464
_young(&_page_table, _old.forwarding_table(), &_page_allocator),
65+
_tlab_usage(),
6566
_initialized(false) {
6667

6768
// Install global heap instance
@@ -131,11 +132,11 @@ size_t ZHeap::unused() const {
131132
}
132133

133134
size_t ZHeap::tlab_capacity() const {
134-
return capacity();
135+
return _tlab_usage.tlab_capacity();
135136
}
136137

137138
size_t ZHeap::tlab_used() const {
138-
return _allocator_eden.tlab_used();
139+
return _tlab_usage.tlab_used();
139140
}
140141

141142
size_t ZHeap::max_tlab_size() const {
@@ -156,6 +157,9 @@ size_t ZHeap::unsafe_max_tlab_alloc() const {
156157

157158
return MIN2(size, max_tlab_size());
158159
}
160+
void ZHeap::reset_tlab_used() {
161+
_tlab_usage.reset();
162+
}
159163

160164
bool ZHeap::is_in(uintptr_t addr) const {
161165
if (addr == 0) {
@@ -219,11 +223,38 @@ void ZHeap::out_of_memory() {
219223
log_info(gc)("Out Of Memory (%s)", Thread::current()->name());
220224
}
221225

226+
static bool is_small_eden_page(ZPage* page) {
227+
return page->type() == ZPageType::small && page->age() == ZPageAge::eden;
228+
}
229+
230+
void ZHeap::account_alloc_page(ZPage* page) {
231+
// Do TLAB accounting for small eden pages
232+
if (is_small_eden_page(page)) {
233+
_tlab_usage.increase_used(page->size());
234+
}
235+
}
236+
237+
void ZHeap::account_undo_alloc_page(ZPage* page) {
238+
// Increase the undo counter
239+
ZStatInc(ZCounterUndoPageAllocation);
240+
241+
// Undo TLAB accounting for small eden pages
242+
if (is_small_eden_page(page)) {
243+
_tlab_usage.decrease_used(page->size());
244+
}
245+
246+
log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: %zu",
247+
p2i(Thread::current()), ZUtils::thread_name(), p2i(page), page->size());
248+
}
249+
222250
ZPage* ZHeap::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZPageAge age) {
223251
ZPage* const page = _page_allocator.alloc_page(type, size, flags, age);
224252
if (page != nullptr) {
225253
// Insert page table entry
226254
_page_table.insert(page);
255+
256+
// Do accounting for the allocated page
257+
account_alloc_page(page);
227258
}
228259

229260
return page;
@@ -232,9 +263,8 @@ ZPage* ZHeap::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags, ZP
232263
void ZHeap::undo_alloc_page(ZPage* page) {
233264
assert(page->is_allocating(), "Invalid page state");
234265

235-
ZStatInc(ZCounterUndoPageAllocation);
236-
log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: %zu",
237-
p2i(Thread::current()), ZUtils::thread_name(), p2i(page), page->size());
266+
// Undo accounting for the page being freed
267+
account_undo_alloc_page(page);
238268

239269
free_page(page);
240270
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "gc/z/zPageTable.hpp"
3434
#include "gc/z/zPageType.hpp"
3535
#include "gc/z/zServiceability.hpp"
36+
#include "gc/z/zTLABUsage.hpp"
3637

3738
class OopFieldClosure;
3839

@@ -55,8 +56,14 @@ class ZHeap {
5556
ZGenerationOld _old;
5657
ZGenerationYoung _young;
5758

59+
ZTLABUsage _tlab_usage;
60+
5861
bool _initialized;
5962

63+
// Page allocation accounting
64+
void account_alloc_page(ZPage* page);
65+
void account_undo_alloc_page(ZPage* page);
66+
6067
public:
6168
static ZHeap* heap();
6269

@@ -81,6 +88,7 @@ class ZHeap {
8188
size_t tlab_used() const;
8289
size_t max_tlab_size() const;
8390
size_t unsafe_max_tlab_alloc() const;
91+
void reset_tlab_used();
8492

8593
bool is_in(uintptr_t addr) const;
8694
bool is_in_page_relaxed(const ZPage* page, zaddress addr) const;

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

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ static const ZStatCounter ZCounterUndoObjectAllocationFailed("Memory", "Undo Obj
4343
ZObjectAllocator::ZObjectAllocator(ZPageAge age)
4444
: _age(age),
4545
_use_per_cpu_shared_small_pages(ZHeuristics::use_per_cpu_shared_small_pages()),
46-
_used(0),
47-
_undone(0),
4846
_shared_small_page(nullptr),
4947
_shared_medium_page(nullptr),
5048
_medium_page_alloc_lock() {}
@@ -58,23 +56,14 @@ ZPage* const* ZObjectAllocator::shared_small_page_addr() const {
5856
}
5957

6058
ZPage* ZObjectAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags flags) {
61-
ZPage* const page = ZHeap::heap()->alloc_page(type, size, flags, _age);
62-
if (page != nullptr) {
63-
// Increment used bytes
64-
Atomic::add(_used.addr(), size);
65-
}
66-
67-
return page;
59+
return ZHeap::heap()->alloc_page(type, size, flags, _age);
6860
}
6961

7062
ZPage* ZObjectAllocator::alloc_page_for_relocation(ZPageType type, size_t size, ZAllocationFlags flags) {
7163
return ZHeap::heap()->alloc_page(type, size, flags, _age);
7264
}
7365

7466
void ZObjectAllocator::undo_alloc_page(ZPage* page) {
75-
// Increment undone bytes
76-
Atomic::add(_undone.addr(), page->size());
77-
7867
ZHeap::heap()->undo_alloc_page(page);
7968
}
8069

@@ -229,23 +218,6 @@ ZPageAge ZObjectAllocator::age() const {
229218
return _age;
230219
}
231220

232-
size_t ZObjectAllocator::used() const {
233-
size_t total_used = 0;
234-
size_t total_undone = 0;
235-
236-
ZPerCPUConstIterator<size_t> iter_used(&_used);
237-
for (const size_t* cpu_used; iter_used.next(&cpu_used);) {
238-
total_used += *cpu_used;
239-
}
240-
241-
ZPerCPUConstIterator<size_t> iter_undone(&_undone);
242-
for (const size_t* cpu_undone; iter_undone.next(&cpu_undone);) {
243-
total_undone += *cpu_undone;
244-
}
245-
246-
return total_used - total_undone;
247-
}
248-
249221
size_t ZObjectAllocator::remaining() const {
250222
assert(Thread::current()->is_Java_thread(), "Should be a Java thread");
251223

@@ -260,10 +232,6 @@ size_t ZObjectAllocator::remaining() const {
260232
void ZObjectAllocator::retire_pages() {
261233
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
262234

263-
// Reset used and undone bytes
264-
_used.set_all(0);
265-
_undone.set_all(0);
266-
267235
// Reset allocation pages
268236
_shared_medium_page.set(nullptr);
269237
_shared_small_page.set_all(nullptr);

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class ZObjectAllocator {
3838
private:
3939
ZPageAge _age;
4040
const bool _use_per_cpu_shared_small_pages;
41-
ZPerCPU<size_t> _used;
42-
ZPerCPU<size_t> _undone;
4341
ZPerCPU<ZPage*> _shared_small_page;
4442
ZContended<ZPage*> _shared_medium_page;
4543
ZLock _medium_page_alloc_lock;
@@ -80,7 +78,6 @@ class ZObjectAllocator {
8078

8179
ZPageAge age() const;
8280

83-
size_t used() const;
8481
size_t remaining() const;
8582

8683
void retire_pages();
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) 2025, 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+
#include "gc/z/zTLABUsage.hpp"
25+
#include "logging/log.hpp"
26+
#include "runtime/atomic.hpp"
27+
28+
ZTLABUsage::ZTLABUsage()
29+
: _used(0),
30+
_used_history() {}
31+
32+
void ZTLABUsage::increase_used(size_t size) {
33+
Atomic::add(&_used, size, memory_order_relaxed);
34+
}
35+
36+
void ZTLABUsage::decrease_used(size_t size) {
37+
precond(size <= _used);
38+
39+
Atomic::sub(&_used, size, memory_order_relaxed);
40+
}
41+
42+
void ZTLABUsage::reset() {
43+
const size_t used = Atomic::xchg(&_used, (size_t) 0);
44+
45+
// Avoid updates when nothing has been allocated since the last YC
46+
if (used == 0) {
47+
return;
48+
}
49+
50+
// Save the old values for logging
51+
const size_t old_tlab_used = tlab_used();
52+
const size_t old_tlab_capacity = tlab_capacity();
53+
54+
// Update the usage history with the current value
55+
_used_history.add(used);
56+
57+
log_debug(gc, tlab)("TLAB usage update: used %zuM -> %zuM, capacity: %zuM -> %zuM",
58+
old_tlab_used / M,
59+
tlab_used() / M,
60+
old_tlab_capacity / M,
61+
tlab_capacity() / M);
62+
}
63+
64+
size_t ZTLABUsage::tlab_used() const {
65+
return _used_history.last();
66+
}
67+
68+
size_t ZTLABUsage::tlab_capacity() const {
69+
return _used_history.davg();
70+
}

0 commit comments

Comments
 (0)