Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8265136: ZGC: Expose GarbageCollectorMXBeans for both pauses and cycles #3483

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -227,11 +227,16 @@ bool ZCollectedHeap::uses_stack_watermark_barrier() const {
}

GrowableArray<GCMemoryManager*> ZCollectedHeap::memory_managers() {
return GrowableArray<GCMemoryManager*>(1, 1, _heap.serviceability_memory_manager());
GrowableArray<GCMemoryManager*> memory_managers(2);
memory_managers.append(_heap.serviceability_cycle_memory_manager());
memory_managers.append(_heap.serviceability_pause_memory_manager());
return memory_managers;
}

GrowableArray<MemoryPool*> ZCollectedHeap::memory_pools() {
return GrowableArray<MemoryPool*>(1, 1, _heap.serviceability_memory_pool());
GrowableArray<MemoryPool*> memory_pools(1);
memory_pools.append(_heap.serviceability_memory_pool());
return memory_pools;
}

void ZCollectedHeap::object_iterate(ObjectClosure* cl) {
@@ -455,8 +455,12 @@ void ZHeap::serviceability_initialize() {
_serviceability.initialize();
}

GCMemoryManager* ZHeap::serviceability_memory_manager() {
return _serviceability.memory_manager();
GCMemoryManager* ZHeap::serviceability_cycle_memory_manager() {
return _serviceability.cycle_memory_manager();
}

GCMemoryManager* ZHeap::serviceability_pause_memory_manager() {
return _serviceability.pause_memory_manager();
}

MemoryPool* ZHeap::serviceability_memory_pool() {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@@ -146,7 +146,8 @@ class ZHeap {

// Serviceability
void serviceability_initialize();
GCMemoryManager* serviceability_memory_manager();
GCMemoryManager* serviceability_cycle_memory_manager();
GCMemoryManager* serviceability_pause_memory_manager();
MemoryPool* serviceability_memory_pool();
ZServiceabilityCounters* serviceability_counters();

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021, 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
@@ -110,16 +110,19 @@ MemoryUsage ZServiceabilityMemoryPool::get_memory_usage() {
return MemoryUsage(initial_size(), used, committed, max_size());
}

ZServiceabilityMemoryManager::ZServiceabilityMemoryManager(ZServiceabilityMemoryPool* pool)
: GCMemoryManager("ZGC", "end of major GC") {
ZServiceabilityMemoryManager::ZServiceabilityMemoryManager(const char* name,
const char* end_message,
ZServiceabilityMemoryPool* pool) :
GCMemoryManager(name, end_message) {
add_pool(pool);
}

ZServiceability::ZServiceability(size_t min_capacity, size_t max_capacity) :
_min_capacity(min_capacity),
_max_capacity(max_capacity),
_memory_pool(_min_capacity, _max_capacity),
_memory_manager(&_memory_pool),
_cycle_memory_manager("ZGC Cycles", "end of GC cycle", &_memory_pool),
_pause_memory_manager("ZGC Pauses", "end of GC pause", &_memory_pool),
_counters(NULL) {}

void ZServiceability::initialize() {
@@ -130,29 +133,43 @@ MemoryPool* ZServiceability::memory_pool() {
return &_memory_pool;
}

GCMemoryManager* ZServiceability::memory_manager() {
return &_memory_manager;
GCMemoryManager* ZServiceability::cycle_memory_manager() {
return &_cycle_memory_manager;
}

GCMemoryManager* ZServiceability::pause_memory_manager() {
return &_pause_memory_manager;
}

ZServiceabilityCounters* ZServiceability::counters() {
return _counters;
}

ZServiceabilityCycleTracer::ZServiceabilityCycleTracer() :
_memory_manager_stats(ZHeap::heap()->serviceability_memory_manager(),
_memory_manager_stats(ZHeap::heap()->serviceability_cycle_memory_manager(),
ZCollectedHeap::heap()->gc_cause(),
true /* allMemoryPoolsAffected */,
true /* recordGCBeginTime */,
true /* recordPreGCUsage */,
true /* recordPeakUsage */,
true /* recordPostGCUsage */,
true /* recordAccumulatedGCTime */,
true /* recordGCEndTime */,
true /* countCollection */) {}
true /* allMemoryPoolsAffected */,
true /* recordGCBeginTime */,
true /* recordPreGCUsage */,
true /* recordPeakUsage */,
true /* recordPostGCUsage */,
true /* recordAccumulatedGCTime */,
true /* recordGCEndTime */,
true /* countCollection */) {}

ZServiceabilityPauseTracer::ZServiceabilityPauseTracer() :
_svc_gc_marker(SvcGCMarker::CONCURRENT),
_counters_stats(ZHeap::heap()->serviceability_counters()->collector_counters()) {}
_counters_stats(ZHeap::heap()->serviceability_counters()->collector_counters()),
_memory_manager_stats(ZHeap::heap()->serviceability_pause_memory_manager(),
ZCollectedHeap::heap()->gc_cause(),
true /* allMemoryPoolsAffected */,
true /* recordGCBeginTime */,
false /* recordPreGCUsage */,
false /* recordPeakUsage */,
false /* recordPostGCUsage */,
true /* recordAccumulatedGCTime */,
true /* recordGCEndTime */,
true /* countCollection */) {}

ZServiceabilityPauseTracer::~ZServiceabilityPauseTracer() {
ZHeap::heap()->serviceability_counters()->update_sizes();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021, 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
@@ -43,15 +43,18 @@ class ZServiceabilityMemoryPool : public CollectedMemoryPool {

class ZServiceabilityMemoryManager : public GCMemoryManager {
public:
ZServiceabilityMemoryManager(ZServiceabilityMemoryPool* pool);
ZServiceabilityMemoryManager(const char* name,
const char* end_message,
ZServiceabilityMemoryPool* pool);
};

class ZServiceability {
private:
const size_t _min_capacity;
const size_t _max_capacity;
ZServiceabilityMemoryPool _memory_pool;
ZServiceabilityMemoryManager _memory_manager;
ZServiceabilityMemoryManager _cycle_memory_manager;
ZServiceabilityMemoryManager _pause_memory_manager;
ZServiceabilityCounters* _counters;

public:
@@ -60,7 +63,8 @@ class ZServiceability {
void initialize();

MemoryPool* memory_pool();
GCMemoryManager* memory_manager();
GCMemoryManager* cycle_memory_manager();
GCMemoryManager* pause_memory_manager();
ZServiceabilityCounters* counters();
};

@@ -74,8 +78,9 @@ class ZServiceabilityCycleTracer : public StackObj {

class ZServiceabilityPauseTracer : public StackObj {
private:
SvcGCMarker _svc_gc_marker;
TraceCollectorStats _counters_stats;
SvcGCMarker _svc_gc_marker;
TraceCollectorStats _counters_stats;
TraceMemoryManagerStats _memory_manager_stats;

public:
ZServiceabilityPauseTracer();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2021, 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
@@ -28,7 +28,8 @@
* @bug 7072527
* @summary JMM GC counters overcount in some cases
* @comment Shenandoah has "ExplicitGCInvokesConcurrent" on by default
* @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false)
* @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false)
* @requires vm.gc != "Z"
* @modules java.management
* @run main/othervm -Xlog:gc gc.TestFullGCCount
*/
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
@@ -53,6 +53,7 @@ public static void main(String[] args) throws Exception {
final long initialCapacity = Long.parseLong(args[0]) * M;
final long maxCapacity = Long.parseLong(args[1]) * M;
final AtomicInteger cycles = new AtomicInteger();
final AtomicInteger pauses = new AtomicInteger();
final AtomicInteger errors = new AtomicInteger();

final NotificationListener listener = (Notification notification, Object ignored) -> {
@@ -85,38 +86,65 @@ public static void main(String[] args) throws Exception {
log(" MemoryUsageAfterGC: " + memoryUsageAfterGC);
log("");

if (name.equals("ZGC")) {
if (name.equals("ZGC Cycles")) {
cycles.incrementAndGet();

if (!action.equals("end of GC cycle")) {
log("ERROR: Action");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getInit() != initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.init");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getUsed() > initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.used");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getCommitted() != initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.committed");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getMax() != maxCapacity) {
log("ERROR: MemoryUsageBeforeGC.max");
errors.incrementAndGet();
}
} else if (name.equals("ZGC Pauses")) {
pauses.incrementAndGet();

if (!action.equals("end of GC pause")) {
log("ERROR: Action");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getInit() != 0) {
log("ERROR: MemoryUsageBeforeGC.init");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getUsed() != 0) {
log("ERROR: MemoryUsageBeforeGC.used");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getCommitted() != 0) {
log("ERROR: MemoryUsageBeforeGC.committed");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getMax() != 0) {
log("ERROR: MemoryUsageBeforeGC.max");
errors.incrementAndGet();
}
} else {
log("ERROR: Name");
errors.incrementAndGet();
}

if (!action.equals("end of major GC")) {
log("ERROR: Action");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getInit() != initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.init");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getUsed() > initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.used");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getCommitted() != initialCapacity) {
log("ERROR: MemoryUsageBeforeGC.committed");
errors.incrementAndGet();
}

if (memoryUsageBeforeGC.getMax() != maxCapacity) {
log("ERROR: MemoryUsageBeforeGC.max");
errors.incrementAndGet();
}

if (!cause.equals("System.gc()")) {
log("ERROR: Cause");
errors.incrementAndGet();
@@ -143,6 +171,7 @@ public static void main(String[] args) throws Exception {
}

final int minCycles = 5;
final int minPauses = minCycles * 3;

// Run GCs
for (int i = 0; i < minCycles; i++) {
@@ -162,17 +191,25 @@ public static void main(String[] args) throws Exception {
}

final int actualCycles = cycles.get();
final int actualPauses = pauses.get();
final int actualErrors = errors.get();

log(" minCycles: " + minCycles);
log(" minPauses: " + minPauses);
log("actualCycles: " + actualCycles);
log("actualPauses: " + actualPauses);
log("actualErrors: " + actualErrors);

// Verify number of cycle events
if (actualCycles < minCycles) {
throw new Exception("Unexpected cycles");
}

// Verify number of pause events
if (actualPauses < minPauses) {
throw new Exception("Unexpected pauses");
}

// Verify number of errors
if (actualErrors != 0) {
throw new Exception("Unexpected errors");