< 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 >