8329488: Move OopStorage code from safepoint cleanup and remove safepoint cleanup code
Reviewed-by: kbarrett, eosterlund
This commit is contained in:
parent
77a217df60
commit
3e9c381166
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -410,7 +410,7 @@ OopStorage::Block::block_for_ptr(const OopStorage* owner, const oop* ptr) {
|
|||||||
// allocations until some entries in it are released.
|
// allocations until some entries in it are released.
|
||||||
//
|
//
|
||||||
// release() is performed lock-free. (Note: This means it can't notify the
|
// release() is performed lock-free. (Note: This means it can't notify the
|
||||||
// service thread of pending cleanup work. It must be lock-free because
|
// ServiceThread of pending cleanup work. It must be lock-free because
|
||||||
// it is called in all kinds of contexts where even quite low ranked locks
|
// it is called in all kinds of contexts where even quite low ranked locks
|
||||||
// may be held.) release() first looks up the block for
|
// may be held.) release() first looks up the block for
|
||||||
// the entry, using address alignment to find the enclosing block (thereby
|
// the entry, using address alignment to find the enclosing block (thereby
|
||||||
@ -705,7 +705,7 @@ void OopStorage::Block::release_entries(uintx releasing, OopStorage* owner) {
|
|||||||
// Only request cleanup for to-empty transitions, not for from-full.
|
// Only request cleanup for to-empty transitions, not for from-full.
|
||||||
// There isn't any rush to process from-full transitions. Allocation
|
// There isn't any rush to process from-full transitions. Allocation
|
||||||
// will reduce deferrals before allocating new blocks, so may process
|
// will reduce deferrals before allocating new blocks, so may process
|
||||||
// some. And the service thread will drain the entire deferred list
|
// some. And the ServiceThread will drain the entire deferred list
|
||||||
// if there are any pending to-empty transitions.
|
// if there are any pending to-empty transitions.
|
||||||
if (releasing == old_allocated) {
|
if (releasing == old_allocated) {
|
||||||
owner->record_needs_cleanup();
|
owner->record_needs_cleanup();
|
||||||
@ -880,67 +880,51 @@ bool OopStorage::should_report_num_dead() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Managing service thread notifications.
|
// Managing service thread notifications.
|
||||||
//
|
|
||||||
// We don't want cleanup work to linger indefinitely, but we also don't want
|
|
||||||
// to run the service thread too often. We're also very limited in what we
|
|
||||||
// can do in a release operation, where cleanup work is created.
|
|
||||||
//
|
|
||||||
// When a release operation changes a block's state to empty, it records the
|
// When a release operation changes a block's state to empty, it records the
|
||||||
// need for cleanup in both the associated storage object and in the global
|
// need for cleanup in both the associated storage object and in the global
|
||||||
// request state. A safepoint cleanup task notifies the service thread when
|
// request state. The ServiceThread checks at timed intervals if
|
||||||
// there may be cleanup work for any storage object, based on the global
|
// there may be cleanup work for any storage object, based on the global
|
||||||
// request state. But that notification is deferred if the service thread
|
// request state. We don't want to run empty block cleanup too often in the
|
||||||
// has run recently, and we also avoid duplicate notifications. The service
|
// face of frequent explicit ServiceThread wakeups, hence the defer period.
|
||||||
// thread updates the timestamp and resets the state flags on every iteration.
|
|
||||||
|
|
||||||
// Global cleanup request state.
|
// Global cleanup request state.
|
||||||
static volatile bool needs_cleanup_requested = false;
|
static volatile bool needs_cleanup_requested = false;
|
||||||
|
|
||||||
// Flag for avoiding duplicate notifications.
|
// Time after which a cleanup is permitted.
|
||||||
static bool needs_cleanup_triggered = false;
|
static jlong cleanup_permit_time = 0;
|
||||||
|
|
||||||
// Time after which a notification can be made.
|
// Minimum time between ServiceThread cleanups.
|
||||||
static jlong cleanup_trigger_permit_time = 0;
|
// The value of 500ms was an arbitrary choice; frequent, but not too frequent.
|
||||||
|
const jlong cleanup_defer_period = 500 * NANOSECS_PER_MILLISEC;
|
||||||
// Minimum time since last service thread check before notification is
|
|
||||||
// permitted. The value of 500ms was an arbitrary choice; frequent, but not
|
|
||||||
// too frequent.
|
|
||||||
const jlong cleanup_trigger_defer_period = 500 * NANOSECS_PER_MILLISEC;
|
|
||||||
|
|
||||||
void OopStorage::trigger_cleanup_if_needed() {
|
|
||||||
MonitorLocker ml(Service_lock, Monitor::_no_safepoint_check_flag);
|
|
||||||
if (Atomic::load(&needs_cleanup_requested) &&
|
|
||||||
!needs_cleanup_triggered &&
|
|
||||||
(os::javaTimeNanos() > cleanup_trigger_permit_time)) {
|
|
||||||
needs_cleanup_triggered = true;
|
|
||||||
ml.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OopStorage::has_cleanup_work_and_reset() {
|
bool OopStorage::has_cleanup_work_and_reset() {
|
||||||
assert_lock_strong(Service_lock);
|
assert_lock_strong(Service_lock);
|
||||||
cleanup_trigger_permit_time =
|
|
||||||
os::javaTimeNanos() + cleanup_trigger_defer_period;
|
if (Atomic::load_acquire(&needs_cleanup_requested) &&
|
||||||
needs_cleanup_triggered = false;
|
os::javaTimeNanos() > cleanup_permit_time) {
|
||||||
// Set the request flag false and return its old value.
|
cleanup_permit_time =
|
||||||
// Needs to be atomic to avoid dropping a concurrent request.
|
os::javaTimeNanos() + cleanup_defer_period;
|
||||||
// Can't use Atomic::xchg, which may not support bool.
|
// Set the request flag false and return its old value.
|
||||||
return Atomic::cmpxchg(&needs_cleanup_requested, true, false);
|
Atomic::release_store(&needs_cleanup_requested, false);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record that cleanup is needed, without notifying the Service thread.
|
// Record that cleanup is needed, without notifying the Service thread, because
|
||||||
// Used by release(), where we can't lock even Service_lock.
|
// we can't lock the Service_lock. Used by release().
|
||||||
void OopStorage::record_needs_cleanup() {
|
void OopStorage::record_needs_cleanup() {
|
||||||
// Set local flag first, else service thread could wake up and miss
|
// Set local flag first, else ServiceThread could wake up and miss
|
||||||
// the request. This order may instead (rarely) unnecessarily notify.
|
// the request.
|
||||||
Atomic::release_store(&_needs_cleanup, true);
|
Atomic::release_store(&_needs_cleanup, true);
|
||||||
Atomic::release_store_fence(&needs_cleanup_requested, true);
|
Atomic::release_store_fence(&needs_cleanup_requested, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OopStorage::delete_empty_blocks() {
|
bool OopStorage::delete_empty_blocks() {
|
||||||
// Service thread might have oopstorage work, but not for this object.
|
// ServiceThread might have oopstorage work, but not for this object.
|
||||||
// Check for deferred updates even though that's not a service thread
|
// But check for deferred updates, which might provide cleanup work.
|
||||||
// trigger; since we're here, we might as well process them.
|
|
||||||
if (!Atomic::load_acquire(&_needs_cleanup) &&
|
if (!Atomic::load_acquire(&_needs_cleanup) &&
|
||||||
(Atomic::load_acquire(&_deferred_updates) == nullptr)) {
|
(Atomic::load_acquire(&_deferred_updates) == nullptr)) {
|
||||||
return false;
|
return false;
|
||||||
@ -986,7 +970,7 @@ bool OopStorage::delete_empty_blocks() {
|
|||||||
// Don't interfere with an active concurrent iteration.
|
// Don't interfere with an active concurrent iteration.
|
||||||
// Instead, give up immediately. There is more work to do,
|
// Instead, give up immediately. There is more work to do,
|
||||||
// but don't re-notify, to avoid useless spinning of the
|
// but don't re-notify, to avoid useless spinning of the
|
||||||
// service thread. Instead, iteration completion notifies.
|
// ServiceThread. Instead, iteration completion notifies.
|
||||||
if (_concurrent_iteration_count > 0) return true;
|
if (_concurrent_iteration_count > 0) return true;
|
||||||
_active_array->remove(block);
|
_active_array->remove(block);
|
||||||
}
|
}
|
||||||
@ -998,10 +982,8 @@ bool OopStorage::delete_empty_blocks() {
|
|||||||
ThreadBlockInVM tbiv(JavaThread::current());
|
ThreadBlockInVM tbiv(JavaThread::current());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Exceeded work limit or can't delete last block. This will
|
// Exceeded work limit or can't delete last block so still needs cleanup
|
||||||
// cause the service thread to loop, giving other subtasks an
|
// for the next time.
|
||||||
// opportunity to run too. There's no need for a notification,
|
|
||||||
// because we are part of the service thread (unless gtesting).
|
|
||||||
record_needs_cleanup();
|
record_needs_cleanup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -684,17 +684,6 @@
|
|||||||
<Field type="int" name="iterations" label="Iterations" description="Number of state check iterations" />
|
<Field type="int" name="iterations" label="Iterations" description="Number of state check iterations" />
|
||||||
</Event>
|
</Event>
|
||||||
|
|
||||||
<Event name="SafepointCleanup" category="Java Virtual Machine, Runtime, Safepoint" label="Safepoint Cleanup" description="Safepointing begin running cleanup tasks"
|
|
||||||
thread="true">
|
|
||||||
<Field type="ulong" name="safepointId" label="Safepoint Identifier" relation="SafepointId" />
|
|
||||||
</Event>
|
|
||||||
|
|
||||||
<Event name="SafepointCleanupTask" category="Java Virtual Machine, Runtime, Safepoint" label="Safepoint Cleanup Task" description="Safepointing begin running cleanup tasks"
|
|
||||||
thread="true">
|
|
||||||
<Field type="ulong" name="safepointId" label="Safepoint Identifier" relation="SafepointId" />
|
|
||||||
<Field type="string" name="name" label="Task Name" description="The task name" />
|
|
||||||
</Event>
|
|
||||||
|
|
||||||
<Event name="SafepointEnd" category="Java Virtual Machine, Runtime, Safepoint" label="Safepoint End" description="Safepointing end" thread="true">
|
<Event name="SafepointEnd" category="Java Virtual Machine, Runtime, Safepoint" label="Safepoint End" description="Safepointing end" thread="true">
|
||||||
<Field type="ulong" name="safepointId" label="Safepoint Identifier" relation="SafepointId" />
|
<Field type="ulong" name="safepointId" label="Safepoint Identifier" relation="SafepointId" />
|
||||||
</Event>
|
</Event>
|
||||||
|
@ -1282,6 +1282,11 @@ const int ObjectAlignmentInBytes = 8;
|
|||||||
"(0 means none)") \
|
"(0 means none)") \
|
||||||
range(0, max_jint) \
|
range(0, max_jint) \
|
||||||
\
|
\
|
||||||
|
product(intx, ServiceThreadCleanupInterval, 1000, DIAGNOSTIC, \
|
||||||
|
"Wake the ServiceThread to do periodic cleanup checks every so " \
|
||||||
|
"many milliseconds (0 means none)") \
|
||||||
|
range(0, max_jint) \
|
||||||
|
\
|
||||||
product(double, SafepointTimeoutDelay, 10000, \
|
product(double, SafepointTimeoutDelay, 10000, \
|
||||||
"Delay in milliseconds for option SafepointTimeout; " \
|
"Delay in milliseconds for option SafepointTimeout; " \
|
||||||
"supports sub-millisecond resolution with fractional values.") \
|
"supports sub-millisecond resolution with fractional values.") \
|
||||||
|
@ -80,12 +80,6 @@ static void post_safepoint_begin_event(EventSafepointBegin& event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void post_safepoint_cleanup_event(EventSafepointCleanup& event, uint64_t safepoint_id) {
|
|
||||||
if (event.should_commit()) {
|
|
||||||
event.set_safepointId(safepoint_id);
|
|
||||||
event.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void post_safepoint_synchronize_event(EventSafepointStateSynchronization& event,
|
static void post_safepoint_synchronize_event(EventSafepointStateSynchronization& event,
|
||||||
uint64_t safepoint_id,
|
uint64_t safepoint_id,
|
||||||
@ -101,16 +95,6 @@ static void post_safepoint_synchronize_event(EventSafepointStateSynchronization&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask& event,
|
|
||||||
uint64_t safepoint_id,
|
|
||||||
const char* name) {
|
|
||||||
if (event.should_commit()) {
|
|
||||||
event.set_safepointId(safepoint_id);
|
|
||||||
event.set_name(name);
|
|
||||||
event.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void post_safepoint_end_event(EventSafepointEnd& event, uint64_t safepoint_id) {
|
static void post_safepoint_end_event(EventSafepointEnd& event, uint64_t safepoint_id) {
|
||||||
if (event.should_commit()) {
|
if (event.should_commit()) {
|
||||||
event.set_safepointId(safepoint_id);
|
event.set_safepointId(safepoint_id);
|
||||||
@ -435,14 +419,7 @@ void SafepointSynchronize::begin() {
|
|||||||
|
|
||||||
SafepointTracing::synchronized(nof_threads, initial_running, _nof_threads_hit_polling_page);
|
SafepointTracing::synchronized(nof_threads, initial_running, _nof_threads_hit_polling_page);
|
||||||
|
|
||||||
// We do the safepoint cleanup first since a GC related safepoint
|
|
||||||
// needs cleanup to be completed before running the GC op.
|
|
||||||
EventSafepointCleanup cleanup_event;
|
|
||||||
do_cleanup_tasks();
|
|
||||||
post_safepoint_cleanup_event(cleanup_event, _safepoint_id);
|
|
||||||
|
|
||||||
post_safepoint_begin_event(begin_event, _safepoint_id, nof_threads, _current_jni_active_count);
|
post_safepoint_begin_event(begin_event, _safepoint_id, nof_threads, _current_jni_active_count);
|
||||||
SafepointTracing::cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafepointSynchronize::disarm_safepoint() {
|
void SafepointSynchronize::disarm_safepoint() {
|
||||||
@ -507,68 +484,6 @@ void SafepointSynchronize::end() {
|
|||||||
post_safepoint_end_event(event, safepoint_id());
|
post_safepoint_end_event(event, safepoint_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParallelCleanupTask : public WorkerTask {
|
|
||||||
private:
|
|
||||||
SubTasksDone _subtasks;
|
|
||||||
|
|
||||||
class Tracer {
|
|
||||||
private:
|
|
||||||
const char* _name;
|
|
||||||
EventSafepointCleanupTask _event;
|
|
||||||
TraceTime _timer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Tracer(const char* name) :
|
|
||||||
_name(name),
|
|
||||||
_event(),
|
|
||||||
_timer(name, TRACETIME_LOG(Info, safepoint, cleanup)) {}
|
|
||||||
~Tracer() {
|
|
||||||
post_safepoint_cleanup_task_event(_event, SafepointSynchronize::safepoint_id(), _name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
ParallelCleanupTask() :
|
|
||||||
WorkerTask("Parallel Safepoint Cleanup"),
|
|
||||||
_subtasks(SafepointSynchronize::SAFEPOINT_CLEANUP_NUM_TASKS) {}
|
|
||||||
|
|
||||||
uint expected_num_workers() const {
|
|
||||||
uint workers = 0;
|
|
||||||
|
|
||||||
return MAX2<uint>(1, workers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void work(uint worker_id) {
|
|
||||||
if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP)) {
|
|
||||||
// Don't bother reporting event or time for this very short operation.
|
|
||||||
// To have any utility we'd also want to report whether needed.
|
|
||||||
OopStorage::trigger_cleanup_if_needed();
|
|
||||||
}
|
|
||||||
|
|
||||||
_subtasks.all_tasks_claimed();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Various cleaning tasks that should be done periodically at safepoints.
|
|
||||||
void SafepointSynchronize::do_cleanup_tasks() {
|
|
||||||
|
|
||||||
TraceTime timer("safepoint cleanup tasks", TRACETIME_LOG(Info, safepoint, cleanup));
|
|
||||||
|
|
||||||
CollectedHeap* heap = Universe::heap();
|
|
||||||
assert(heap != nullptr, "heap not initialized yet?");
|
|
||||||
ParallelCleanupTask cleanup;
|
|
||||||
WorkerThreads* cleanup_workers = heap->safepoint_workers();
|
|
||||||
const uint expected_num_workers = cleanup.expected_num_workers();
|
|
||||||
if (cleanup_workers != nullptr && expected_num_workers > 1) {
|
|
||||||
// Parallel cleanup using GC provided thread pool.
|
|
||||||
const uint num_workers = MIN2(expected_num_workers, cleanup_workers->active_workers());
|
|
||||||
cleanup_workers->run_task(&cleanup, num_workers);
|
|
||||||
} else {
|
|
||||||
// Serial cleanup using VMThread.
|
|
||||||
cleanup.work(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for determining if a JavaThread is safepoint safe.
|
// Methods for determining if a JavaThread is safepoint safe.
|
||||||
|
|
||||||
// False means unsafe with undetermined state.
|
// False means unsafe with undetermined state.
|
||||||
@ -946,7 +861,6 @@ void ThreadSafepointState::handle_polling_page_exception() {
|
|||||||
|
|
||||||
jlong SafepointTracing::_last_safepoint_begin_time_ns = 0;
|
jlong SafepointTracing::_last_safepoint_begin_time_ns = 0;
|
||||||
jlong SafepointTracing::_last_safepoint_sync_time_ns = 0;
|
jlong SafepointTracing::_last_safepoint_sync_time_ns = 0;
|
||||||
jlong SafepointTracing::_last_safepoint_cleanup_time_ns = 0;
|
|
||||||
jlong SafepointTracing::_last_safepoint_end_time_ns = 0;
|
jlong SafepointTracing::_last_safepoint_end_time_ns = 0;
|
||||||
jlong SafepointTracing::_last_app_time_ns = 0;
|
jlong SafepointTracing::_last_app_time_ns = 0;
|
||||||
int SafepointTracing::_nof_threads = 0;
|
int SafepointTracing::_nof_threads = 0;
|
||||||
@ -954,7 +868,6 @@ int SafepointTracing::_nof_running = 0;
|
|||||||
int SafepointTracing::_page_trap = 0;
|
int SafepointTracing::_page_trap = 0;
|
||||||
VM_Operation::VMOp_Type SafepointTracing::_current_type;
|
VM_Operation::VMOp_Type SafepointTracing::_current_type;
|
||||||
jlong SafepointTracing::_max_sync_time = 0;
|
jlong SafepointTracing::_max_sync_time = 0;
|
||||||
jlong SafepointTracing::_max_cleanup_time = 0;
|
|
||||||
jlong SafepointTracing::_max_vmop_time = 0;
|
jlong SafepointTracing::_max_vmop_time = 0;
|
||||||
uint64_t SafepointTracing::_op_count[VM_Operation::VMOp_Terminating] = {0};
|
uint64_t SafepointTracing::_op_count[VM_Operation::VMOp_Terminating] = {0};
|
||||||
|
|
||||||
@ -970,7 +883,7 @@ static void print_header(outputStream* st) {
|
|||||||
|
|
||||||
st->print("VM Operation "
|
st->print("VM Operation "
|
||||||
"[ threads: total initial_running ]"
|
"[ threads: total initial_running ]"
|
||||||
"[ time: sync cleanup vmop total ]");
|
"[ time: sync vmop total ]");
|
||||||
|
|
||||||
st->print_cr(" page_trap_count");
|
st->print_cr(" page_trap_count");
|
||||||
}
|
}
|
||||||
@ -999,11 +912,9 @@ void SafepointTracing::statistics_log() {
|
|||||||
_nof_threads,
|
_nof_threads,
|
||||||
_nof_running);
|
_nof_running);
|
||||||
ls.print("[ "
|
ls.print("[ "
|
||||||
INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " "
|
INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " ]",
|
||||||
INT64_FORMAT_W(10) " " INT64_FORMAT_W(10) " ]",
|
|
||||||
(int64_t)(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns),
|
(int64_t)(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns),
|
||||||
(int64_t)(_last_safepoint_cleanup_time_ns - _last_safepoint_sync_time_ns),
|
(int64_t)(_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns),
|
||||||
(int64_t)(_last_safepoint_end_time_ns - _last_safepoint_cleanup_time_ns),
|
|
||||||
(int64_t)(_last_safepoint_end_time_ns - _last_safepoint_begin_time_ns));
|
(int64_t)(_last_safepoint_end_time_ns - _last_safepoint_begin_time_ns));
|
||||||
|
|
||||||
ls.print_cr(INT32_FORMAT_W(16), _page_trap);
|
ls.print_cr(INT32_FORMAT_W(16), _page_trap);
|
||||||
@ -1024,8 +935,6 @@ void SafepointTracing::statistics_exit_log() {
|
|||||||
|
|
||||||
log_info(safepoint, stats)("Maximum sync time " INT64_FORMAT" ns",
|
log_info(safepoint, stats)("Maximum sync time " INT64_FORMAT" ns",
|
||||||
(int64_t)(_max_sync_time));
|
(int64_t)(_max_sync_time));
|
||||||
log_info(safepoint, stats)("Maximum cleanup time " INT64_FORMAT" ns",
|
|
||||||
(int64_t)(_max_cleanup_time));
|
|
||||||
log_info(safepoint, stats)("Maximum vm operation time (except for Exit VM operation) "
|
log_info(safepoint, stats)("Maximum vm operation time (except for Exit VM operation) "
|
||||||
INT64_FORMAT " ns",
|
INT64_FORMAT " ns",
|
||||||
(int64_t)(_max_vmop_time));
|
(int64_t)(_max_vmop_time));
|
||||||
@ -1038,7 +947,6 @@ void SafepointTracing::begin(VM_Operation::VMOp_Type type) {
|
|||||||
// update the time stamp to begin recording safepoint time
|
// update the time stamp to begin recording safepoint time
|
||||||
_last_safepoint_begin_time_ns = os::javaTimeNanos();
|
_last_safepoint_begin_time_ns = os::javaTimeNanos();
|
||||||
_last_safepoint_sync_time_ns = 0;
|
_last_safepoint_sync_time_ns = 0;
|
||||||
_last_safepoint_cleanup_time_ns = 0;
|
|
||||||
|
|
||||||
_last_app_time_ns = _last_safepoint_begin_time_ns - _last_safepoint_end_time_ns;
|
_last_app_time_ns = _last_safepoint_begin_time_ns - _last_safepoint_end_time_ns;
|
||||||
_last_safepoint_end_time_ns = 0;
|
_last_safepoint_end_time_ns = 0;
|
||||||
@ -1054,19 +962,12 @@ void SafepointTracing::synchronized(int nof_threads, int nof_running, int traps)
|
|||||||
RuntimeService::record_safepoint_synchronized(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns);
|
RuntimeService::record_safepoint_synchronized(_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SafepointTracing::cleanup() {
|
|
||||||
_last_safepoint_cleanup_time_ns = os::javaTimeNanos();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SafepointTracing::end() {
|
void SafepointTracing::end() {
|
||||||
_last_safepoint_end_time_ns = os::javaTimeNanos();
|
_last_safepoint_end_time_ns = os::javaTimeNanos();
|
||||||
|
|
||||||
if (_max_sync_time < (_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns)) {
|
if (_max_sync_time < (_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns)) {
|
||||||
_max_sync_time = _last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns;
|
_max_sync_time = _last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns;
|
||||||
}
|
}
|
||||||
if (_max_cleanup_time < (_last_safepoint_cleanup_time_ns - _last_safepoint_sync_time_ns)) {
|
|
||||||
_max_cleanup_time = _last_safepoint_cleanup_time_ns - _last_safepoint_sync_time_ns;
|
|
||||||
}
|
|
||||||
if (_max_vmop_time < (_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns)) {
|
if (_max_vmop_time < (_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns)) {
|
||||||
_max_vmop_time = _last_safepoint_end_time_ns - _last_safepoint_sync_time_ns;
|
_max_vmop_time = _last_safepoint_end_time_ns - _last_safepoint_sync_time_ns;
|
||||||
}
|
}
|
||||||
@ -1078,14 +979,12 @@ void SafepointTracing::end() {
|
|||||||
"Safepoint \"%s\", "
|
"Safepoint \"%s\", "
|
||||||
"Time since last: " JLONG_FORMAT " ns, "
|
"Time since last: " JLONG_FORMAT " ns, "
|
||||||
"Reaching safepoint: " JLONG_FORMAT " ns, "
|
"Reaching safepoint: " JLONG_FORMAT " ns, "
|
||||||
"Cleanup: " JLONG_FORMAT " ns, "
|
|
||||||
"At safepoint: " JLONG_FORMAT " ns, "
|
"At safepoint: " JLONG_FORMAT " ns, "
|
||||||
"Total: " JLONG_FORMAT " ns",
|
"Total: " JLONG_FORMAT " ns",
|
||||||
VM_Operation::name(_current_type),
|
VM_Operation::name(_current_type),
|
||||||
_last_app_time_ns,
|
_last_app_time_ns,
|
||||||
_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns,
|
_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns,
|
||||||
_last_safepoint_cleanup_time_ns - _last_safepoint_sync_time_ns,
|
_last_safepoint_end_time_ns - _last_safepoint_sync_time_ns,
|
||||||
_last_safepoint_end_time_ns - _last_safepoint_cleanup_time_ns,
|
|
||||||
_last_safepoint_end_time_ns - _last_safepoint_begin_time_ns
|
_last_safepoint_end_time_ns - _last_safepoint_begin_time_ns
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -68,13 +68,6 @@ class SafepointSynchronize : AllStatic {
|
|||||||
// VM thread and any NonJavaThread may be running.
|
// VM thread and any NonJavaThread may be running.
|
||||||
};
|
};
|
||||||
|
|
||||||
// The enums are listed in the order of the tasks when done serially.
|
|
||||||
enum SafepointCleanupTasks {
|
|
||||||
SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP,
|
|
||||||
// Leave this one last.
|
|
||||||
SAFEPOINT_CLEANUP_NUM_TASKS
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SafepointMechanism;
|
friend class SafepointMechanism;
|
||||||
friend class ThreadSafepointState;
|
friend class ThreadSafepointState;
|
||||||
@ -155,8 +148,6 @@ public:
|
|||||||
// Exception handling for page polling
|
// Exception handling for page polling
|
||||||
static void handle_polling_page_exception(JavaThread *thread);
|
static void handle_polling_page_exception(JavaThread *thread);
|
||||||
|
|
||||||
static void do_cleanup_tasks();
|
|
||||||
|
|
||||||
static void set_is_at_safepoint() { _state = _synchronized; }
|
static void set_is_at_safepoint() { _state = _synchronized; }
|
||||||
static void set_is_not_at_safepoint() { _state = _not_synchronized; }
|
static void set_is_not_at_safepoint() { _state = _not_synchronized; }
|
||||||
|
|
||||||
@ -239,7 +230,6 @@ private:
|
|||||||
// Absolute
|
// Absolute
|
||||||
static jlong _last_safepoint_begin_time_ns;
|
static jlong _last_safepoint_begin_time_ns;
|
||||||
static jlong _last_safepoint_sync_time_ns;
|
static jlong _last_safepoint_sync_time_ns;
|
||||||
static jlong _last_safepoint_cleanup_time_ns;
|
|
||||||
static jlong _last_safepoint_end_time_ns;
|
static jlong _last_safepoint_end_time_ns;
|
||||||
|
|
||||||
// Relative
|
// Relative
|
||||||
@ -251,7 +241,6 @@ private:
|
|||||||
|
|
||||||
static VM_Operation::VMOp_Type _current_type;
|
static VM_Operation::VMOp_Type _current_type;
|
||||||
static jlong _max_sync_time;
|
static jlong _max_sync_time;
|
||||||
static jlong _max_cleanup_time;
|
|
||||||
static jlong _max_vmop_time;
|
static jlong _max_vmop_time;
|
||||||
static uint64_t _op_count[VM_Operation::VMOp_Terminating];
|
static uint64_t _op_count[VM_Operation::VMOp_Terminating];
|
||||||
|
|
||||||
@ -262,7 +251,6 @@ public:
|
|||||||
|
|
||||||
static void begin(VM_Operation::VMOp_Type type);
|
static void begin(VM_Operation::VMOp_Type type);
|
||||||
static void synchronized(int nof_threads, int nof_running, int traps);
|
static void synchronized(int nof_threads, int nof_running, int traps);
|
||||||
static void cleanup();
|
|
||||||
static void end();
|
static void end();
|
||||||
|
|
||||||
static void statistics_exit_log();
|
static void statistics_exit_log();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -126,8 +126,9 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
|||||||
(cldg_cleanup_work = ClassLoaderDataGraph::should_clean_metaspaces_and_reset()) |
|
(cldg_cleanup_work = ClassLoaderDataGraph::should_clean_metaspaces_and_reset()) |
|
||||||
(jvmti_tagmap_work = JvmtiTagMap::has_object_free_events_and_reset())
|
(jvmti_tagmap_work = JvmtiTagMap::has_object_free_events_and_reset())
|
||||||
) == 0) {
|
) == 0) {
|
||||||
// Wait until notified that there is some work to do.
|
// Wait until notified that there is some work to do or timer expires.
|
||||||
ml.wait();
|
// Some cleanup requests don't notify the ServiceThread so work needs to be done at periodic intervals.
|
||||||
|
ml.wait(ServiceThreadCleanupInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_jvmti_events) {
|
if (has_jvmti_events) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
;
|
;
|
||||||
; Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
; Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
;
|
;
|
||||||
; This code is free software; you can redistribute it and/or modify it
|
; This code is free software; you can redistribute it and/or modify it
|
||||||
@ -525,13 +525,13 @@ form = "COLUMN 'Event Count', 'First Recorded Event', 'Last Recorded Event',
|
|||||||
[jvm.safepoints]
|
[jvm.safepoints]
|
||||||
label = "Safepoints"
|
label = "Safepoints"
|
||||||
table = "COLUMN 'Start Time', 'Duration',
|
table = "COLUMN 'Start Time', 'Duration',
|
||||||
'State Syncronization', 'Cleanup',
|
'State Syncronization',
|
||||||
'JNI Critical Threads', 'Total Threads'
|
'JNI Critical Threads', 'Total Threads'
|
||||||
SELECT B.startTime, DIFF([B|E].startTime),
|
SELECT B.startTime, DIFF([B|E].startTime),
|
||||||
S.duration, C.duration,
|
S.duration,
|
||||||
jniCriticalThreadCount, totalThreadCount
|
jniCriticalThreadCount, totalThreadCount
|
||||||
FROM SafepointBegin AS B, SafepointEnd AS E,
|
FROM SafepointBegin AS B, SafepointEnd AS E,
|
||||||
SafepointCleanup AS C, SafepointStateSynchronization AS S
|
SafepointStateSynchronization AS S
|
||||||
GROUP BY safepointId ORDER BY B.startTime"
|
GROUP BY safepointId ORDER BY B.startTime"
|
||||||
|
|
||||||
[jvm.longest-compilations]
|
[jvm.longest-compilations]
|
||||||
|
@ -200,16 +200,6 @@
|
|||||||
<setting name="threshold">10 ms</setting>
|
<setting name="threshold">10 ms</setting>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event name="jdk.SafepointCleanup">
|
|
||||||
<setting name="enabled">false</setting>
|
|
||||||
<setting name="threshold">10 ms</setting>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="jdk.SafepointCleanupTask">
|
|
||||||
<setting name="enabled">false</setting>
|
|
||||||
<setting name="threshold">10 ms</setting>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="jdk.SafepointEnd">
|
<event name="jdk.SafepointEnd">
|
||||||
<setting name="enabled">false</setting>
|
<setting name="enabled">false</setting>
|
||||||
<setting name="threshold">10 ms</setting>
|
<setting name="threshold">10 ms</setting>
|
||||||
|
@ -200,16 +200,6 @@
|
|||||||
<setting name="threshold">0 ms</setting>
|
<setting name="threshold">0 ms</setting>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event name="jdk.SafepointCleanup">
|
|
||||||
<setting name="enabled">false</setting>
|
|
||||||
<setting name="threshold">0 ms</setting>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="jdk.SafepointCleanupTask">
|
|
||||||
<setting name="enabled">false</setting>
|
|
||||||
<setting name="threshold">0 ms</setting>
|
|
||||||
</event>
|
|
||||||
|
|
||||||
<event name="jdk.SafepointEnd">
|
<event name="jdk.SafepointEnd">
|
||||||
<setting name="enabled">false</setting>
|
<setting name="enabled">false</setting>
|
||||||
<setting name="threshold">0 ms</setting>
|
<setting name="threshold">0 ms</setting>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -55,7 +55,7 @@ public class TestReclaimStringsLeaksMemory {
|
|||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
ArrayList<String> baseargs = new ArrayList<>(Arrays.asList("-Xms256M",
|
ArrayList<String> baseargs = new ArrayList<>(Arrays.asList("-Xms256M",
|
||||||
"-Xmx256M",
|
"-Xmx256M",
|
||||||
"-Xlog:gc*,stringtable*=debug:gc.log",
|
"-Xlog:gc*,stringtable*=debug,oopstorage+blocks=debug:gc.log",
|
||||||
"-XX:NativeMemoryTracking=summary",
|
"-XX:NativeMemoryTracking=summary",
|
||||||
"-XX:+UnlockDiagnosticVMOptions",
|
"-XX:+UnlockDiagnosticVMOptions",
|
||||||
"-XX:+PrintNMTStatistics" ));
|
"-XX:+PrintNMTStatistics" ));
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016, 2023, 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @test
|
|
||||||
* @bug 8149991
|
|
||||||
* @summary safepoint+cleanup=info should have output from the code
|
|
||||||
* @requires vm.flagless
|
|
||||||
* @library /test/lib
|
|
||||||
* @modules java.base/jdk.internal.misc
|
|
||||||
* java.management
|
|
||||||
* @run driver SafepointCleanupTest
|
|
||||||
*/
|
|
||||||
|
|
||||||
import jdk.test.lib.process.OutputAnalyzer;
|
|
||||||
import jdk.test.lib.process.ProcessTools;
|
|
||||||
|
|
||||||
public class SafepointCleanupTest {
|
|
||||||
static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
|
|
||||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
||||||
output.shouldContain("[safepoint,cleanup]");
|
|
||||||
output.shouldContain("safepoint cleanup tasks");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void analyzeOutputOff(ProcessBuilder pb) throws Exception {
|
|
||||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
|
||||||
output.shouldNotContain("[safepoint,cleanup]");
|
|
||||||
output.shouldHaveExitValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:safepoint+cleanup=info",
|
|
||||||
InnerClass.class.getName());
|
|
||||||
analyzeOutputOn(pb);
|
|
||||||
|
|
||||||
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:safepoint+cleanup=off",
|
|
||||||
InnerClass.class.getName());
|
|
||||||
analyzeOutputOff(pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class InnerClass {
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
System.out.println("Safepoint Cleanup test");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -56,8 +56,7 @@ public class TestLookForUntestedEvents {
|
|||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
"DataLoss", "IntFlag", "ReservedStackActivation", "NativeLibraryUnload",
|
"DataLoss", "IntFlag", "ReservedStackActivation", "NativeLibraryUnload",
|
||||||
"DoubleFlag", "UnsignedLongFlagChanged", "IntFlagChanged",
|
"DoubleFlag", "UnsignedLongFlagChanged", "IntFlagChanged",
|
||||||
"UnsignedIntFlag", "UnsignedIntFlagChanged", "DoubleFlagChanged",
|
"UnsignedIntFlag", "UnsignedIntFlagChanged", "DoubleFlagChanged")
|
||||||
"SafepointCleanupTask")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// GC uses specific framework to test the events, instead of using event names literally.
|
// GC uses specific framework to test the events, instead of using event names literally.
|
||||||
|
@ -52,7 +52,6 @@ public class TestSafepointEvents {
|
|||||||
static final String[] EVENT_NAMES = new String[] {
|
static final String[] EVENT_NAMES = new String[] {
|
||||||
EventNames.SafepointBegin,
|
EventNames.SafepointBegin,
|
||||||
EventNames.SafepointStateSynchronization,
|
EventNames.SafepointStateSynchronization,
|
||||||
EventNames.SafepointCleanup,
|
|
||||||
EventNames.SafepointEnd
|
EventNames.SafepointEnd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -65,8 +65,6 @@ public class EventNames {
|
|||||||
public static final String ClassUnload = PREFIX + "ClassUnload";
|
public static final String ClassUnload = PREFIX + "ClassUnload";
|
||||||
public static final String SafepointBegin = PREFIX + "SafepointBegin";
|
public static final String SafepointBegin = PREFIX + "SafepointBegin";
|
||||||
public static final String SafepointStateSynchronization = PREFIX + "SafepointStateSynchronization";
|
public static final String SafepointStateSynchronization = PREFIX + "SafepointStateSynchronization";
|
||||||
public static final String SafepointCleanup = PREFIX + "SafepointCleanup";
|
|
||||||
public static final String SafepointCleanupTask = PREFIX + "SafepointCleanupTask";
|
|
||||||
public static final String SafepointEnd = PREFIX + "SafepointEnd";
|
public static final String SafepointEnd = PREFIX + "SafepointEnd";
|
||||||
public static final String ExecuteVMOperation = PREFIX + "ExecuteVMOperation";
|
public static final String ExecuteVMOperation = PREFIX + "ExecuteVMOperation";
|
||||||
public static final String Shutdown = PREFIX + "Shutdown";
|
public static final String Shutdown = PREFIX + "Shutdown";
|
||||||
|
Loading…
Reference in New Issue
Block a user