< prev index next >
src/share/vm/jfr/recorder/service/jfrRecorderService.cpp
Print this page
rev 9055 : 8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
Reviewed-by: egahlin, rwestberg
@@ -22,11 +22,13 @@
*
*/
#include "precompiled.hpp"
#include "jfr/jni/jfrJavaSupport.hpp"
+#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
+#include "jfr/leakprofiler/sampling/objectSampler.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
#include "jfr/recorder/repository/jfrChunkRotation.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
@@ -332,10 +334,11 @@
void JfrRecorderService::prepare_for_vm_error_rotation() {
if (!_chunkwriter.is_valid()) {
open_new_chunk(true);
}
_checkpoint_manager.register_service_thread(Thread::current());
+ JfrMetadataEvent::lock();
}
void JfrRecorderService::open_new_chunk(bool vm_error) {
assert(!_chunkwriter.is_valid(), "invariant");
assert(!JfrStream_lock->owned_by_self(), "invariant");
@@ -395,10 +398,15 @@
WriteStackTraceRepository write_stacktrace_repo(stack_trace_repo, chunkwriter, clear);
WriteStackTraceCheckpoint write_stack_trace_checkpoint(chunkwriter, TYPE_STACKTRACE, write_stacktrace_repo);
write_stack_trace_checkpoint.process();
}
+static void write_object_sample_stacktrace(ObjectSampler* sampler, JfrStackTraceRepository& stack_trace_repository) {
+ WriteObjectSampleStacktrace object_sample_stacktrace(sampler, stack_trace_repository);
+ object_sample_stacktrace.process();
+}
+
static void write_stringpool_checkpoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
WriteStringPool write_string_pool(string_pool);
WriteStringPoolCheckpoint write_string_pool_checkpoint(chunkwriter, TYPE_STRING, write_string_pool);
write_string_pool_checkpoint.process();
}
@@ -415,38 +423,40 @@
// lock stream lock ->
// write non-safepoint dependent types ->
// write checkpoint epoch transition list->
// write stack trace checkpoint ->
// write string pool checkpoint ->
+// write object sample stacktraces ->
// write storage ->
// release stream lock
//
void JfrRecorderService::pre_safepoint_write() {
MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
assert(_chunkwriter.is_valid(), "invariant");
_checkpoint_manager.write_types();
_checkpoint_manager.write_epoch_transition_mspace();
write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, false);
write_stringpool_checkpoint(_string_pool, _chunkwriter);
+ if (LeakProfiler::is_running()) {
+ // Exclusive access to the object sampler instance.
+ // The sampler is released (unlocked) later in post_safepoint_write.
+ ObjectSampler* const sampler = ObjectSampler::acquire();
+ assert(sampler != NULL, "invariant");
+ write_object_sample_stacktrace(sampler, _stack_trace_repository);
+ }
_storage.write();
}
void JfrRecorderService::invoke_safepoint_write() {
JfrVMOperation<JfrRecorderService, &JfrRecorderService::safepoint_write> safepoint_task(*this);
VMThread::execute(&safepoint_task);
}
-static void write_object_sample_stacktrace(JfrStackTraceRepository& stack_trace_repository) {
- WriteObjectSampleStacktrace object_sample_stacktrace(stack_trace_repository);
- object_sample_stacktrace.process();
-}
-
//
// safepoint write sequence
//
// lock stream lock ->
-// write object sample stacktraces ->
// write stacktrace repository ->
// write string pool ->
// write safepoint dependent types ->
// write storage ->
// shift_epoch ->
@@ -455,11 +465,10 @@
// release stream lock
//
void JfrRecorderService::safepoint_write() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
- write_object_sample_stacktrace(_stack_trace_repository);
write_stacktrace_checkpoint(_stack_trace_repository, _chunkwriter, true);
write_stringpool_checkpoint_safepoint(_string_pool, _chunkwriter);
_checkpoint_manager.write_safepoint_types();
_storage.write_at_safepoint();
_checkpoint_manager.shift_epoch();
@@ -475,12 +484,13 @@
}
//
// post-safepoint write sequence
//
-// lock stream lock ->
// write type set ->
+// release object sampler ->
+// lock stream lock ->
// write checkpoints ->
// write metadata event ->
// write chunk header ->
// close chunk fd ->
// release stream lock
@@ -490,11 +500,15 @@
// During the safepoint tasks just completed, the system transitioned to a new epoch.
// Type tagging is epoch relative which entails we are able to write out the
// already tagged artifacts for the previous epoch. We can accomplish this concurrently
// with threads now tagging artifacts in relation to the new, now updated, epoch and remain outside of a safepoint.
_checkpoint_manager.write_type_set();
- MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+ if (LeakProfiler::is_running()) {
+ // The object sampler instance was exclusively acquired and locked in pre_safepoint_write.
+ // Note: There is a dependency on write_type_set() above, ensure the release is subsequent.
+ ObjectSampler::release();
+ } MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
// serialize any outstanding checkpoint memory
_checkpoint_manager.write();
// serialize the metadata descriptor event and close out the chunk
_repository.close_chunk(write_metadata_event(_chunkwriter));
assert(!_chunkwriter.is_valid(), "invariant");
@@ -509,15 +523,13 @@
}
void JfrRecorderService::finalize_current_chunk_on_vm_error() {
assert(_chunkwriter.is_valid(), "invariant");
pre_safepoint_write();
- JfrMetadataEvent::lock();
// Do not attempt safepoint dependent operations during emergency dump.
// Optimistically write tagged artifacts.
_checkpoint_manager.shift_epoch();
- _checkpoint_manager.write_type_set();
// update time
_chunkwriter.time_stamp_chunk_now();
post_safepoint_write();
assert(!_chunkwriter.is_valid(), "invariant");
}
< prev index next >