8215284: Reduce noise induced by periodic task getFileSize()
authormgronlun
Thu, 13 Dec 2018 14:36:54 +0100
changeset 53014 339d2fbe8675
parent 53013 c8b2a408628b
child 53015 632c4baddbb8
8215284: Reduce noise induced by periodic task getFileSize() Reviewed-by: redestad, egahlin
src/hotspot/share/jfr/jni/jfrJniMethod.cpp
src/hotspot/share/jfr/jni/jfrJniMethod.hpp
src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp
src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp
src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.cpp
src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.hpp
src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp	Thu Dec 13 14:36:54 2018 +0100
@@ -33,7 +33,7 @@
 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
 #include "jfr/recorder/repository/jfrRepository.hpp"
-#include "jfr/recorder/repository/jfrChunkSizeNotifier.hpp"
+#include "jfr/recorder/repository/jfrChunkRotation.hpp"
 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 #include "jfr/recorder/service/jfrOptionSet.hpp"
 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
@@ -114,7 +114,7 @@
 NO_TRANSITION_END
 
 NO_TRANSITION(void, jfr_set_file_notification(JNIEnv* env, jobject jvm, jlong threshold))
-  JfrChunkSizeNotifier::set_chunk_size_threshold((size_t)threshold);
+  JfrChunkRotation::set_threshold((intptr_t)threshold);
 NO_TRANSITION_END
 
 NO_TRANSITION(void, jfr_set_sample_threads(JNIEnv* env, jobject jvm, jboolean sampleThreads))
@@ -173,6 +173,9 @@
   return JfrEventSetting::set_cutoff(event_type_id, cutoff_ticks) ? JNI_TRUE : JNI_FALSE;
 NO_TRANSITION_END
 
+NO_TRANSITION(jboolean, jfr_should_rotate_disk(JNIEnv* env, jobject jvm))
+  return JfrChunkRotation::should_rotate() ? JNI_TRUE : JNI_FALSE;
+NO_TRANSITION_END
 
 /*
  * JVM_ENTRY_NO_ENV entries
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp	Thu Dec 13 14:36:54 2018 +0100
@@ -129,6 +129,9 @@
 
 void JNICALL jfr_emit_old_object_samples(JNIEnv* env, jobject jvm, jlong cutoff_ticks, jboolean);
 
+jboolean JNICALL jfr_should_rotate_disk(JNIEnv* env, jobject jvm);
+
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp	Thu Dec 13 14:36:54 2018 +0100
@@ -78,7 +78,8 @@
       (char*)"setForceInstrumentation", (char*)"(Z)V", (void*)jfr_set_force_instrumentation,
       (char*)"getUnloadedEventClassCount", (char*)"()J", (void*)jfr_get_unloaded_event_classes_count,
       (char*)"setCutoff", (char*)"(JJ)Z", (void*)jfr_set_cutoff,
-      (char*)"emitOldObjectSamples", (char*)"(JZ)V", (void*)jfr_emit_old_object_samples
+      (char*)"emitOldObjectSamples", (char*)"(JZ)V", (void*)jfr_emit_old_object_samples,
+      (char*)"shouldRotateDisk", (char*)"()Z", (void*)jfr_should_rotate_disk
     };
 
     const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.cpp	Thu Dec 13 14:36:54 2018 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, 2018, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "jfr/jni/jfrJavaSupport.hpp"
+#include "jfr/recorder/repository/jfrChunkRotation.hpp"
+#include "jfr/recorder/repository/jfrChunkWriter.hpp"
+
+static jobject chunk_monitor = NULL;
+static intptr_t threshold = 0;
+static bool rotate = false;
+
+static jobject install_chunk_monitor(Thread* thread) {
+  assert(chunk_monitor == NULL, "invariant");
+  // read static field
+  HandleMark hm(thread);
+  static const char klass[] = "jdk/jfr/internal/JVM";
+  static const char field[] = "FILE_DELTA_CHANGE";
+  static const char signature[] = "Ljava/lang/Object;";
+  JavaValue result(T_OBJECT);
+  JfrJavaArguments field_args(&result, klass, field, signature, thread);
+  JfrJavaSupport::get_field_global_ref(&field_args, thread);
+  chunk_monitor = result.get_jobject();
+  return chunk_monitor;
+}
+
+// lazy install
+static jobject get_chunk_monitor(Thread* thread) {
+  return chunk_monitor != NULL ? chunk_monitor : install_chunk_monitor(thread);
+}
+
+static void notify() {
+  Thread* const thread = Thread::current();
+  JfrJavaSupport::notify_all(get_chunk_monitor(thread), thread);
+}
+
+void JfrChunkRotation::evaluate(const JfrChunkWriter& writer) {
+  assert(threshold > 0, "invariant");
+  if (rotate) {
+    // already in progress
+    return;
+  }
+  assert(!rotate, "invariant");
+  if (writer.size_written() > threshold) {
+    rotate = true;
+    notify();
+  }
+}
+
+bool JfrChunkRotation::should_rotate() {
+  return rotate;
+}
+
+void JfrChunkRotation::on_rotation() {
+  rotate = false;
+}
+
+void JfrChunkRotation::set_threshold(intptr_t bytes) {
+  threshold = bytes;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkRotation.hpp	Thu Dec 13 14:36:54 2018 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2018, 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.
+ *
+ */
+
+#ifndef SHARE_VM_JFR_RECORDER_REPOSITORY_JFRCHUNKROTATION_HPP
+#define SHARE_VM_JFR_RECORDER_REPOSITORY_JFRCHUNKROTATION_HPP
+
+#include "memory/allocation.hpp"
+
+class JfrChunkWriter;
+
+//
+// Responsible for notifications about current chunk size now exceeding threshold.
+// This is a means to initiate a chunk rotation on the basis of the size written.
+//
+class JfrChunkRotation : AllStatic {
+ public:
+  static void evaluate(const JfrChunkWriter& writer);
+  static void set_threshold(intptr_t bytes);
+  static bool should_rotate();
+  static void on_rotation();
+};
+
+#endif // SHARE_VM_JFR_RECORDER_REPOSITORY_JFRCHUNKROTATION_HPP
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.cpp	Thu Dec 13 14:21:04 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "jfr/jni/jfrJavaSupport.hpp"
-#include "jfr/recorder/repository/jfrChunkWriter.hpp"
-#include "jfr/recorder/repository/jfrChunkSizeNotifier.hpp"
-
-size_t JfrChunkSizeNotifier::_chunk_size_threshold = 0;
-
-void JfrChunkSizeNotifier::set_chunk_size_threshold(size_t bytes) {
-  _chunk_size_threshold = bytes;
-}
-
-size_t JfrChunkSizeNotifier::chunk_size_threshold() {
-  return _chunk_size_threshold;
-}
-
-static jobject new_chunk_monitor = NULL;
-
-// lazy install
-static jobject get_new_chunk_monitor(Thread* thread) {
-  static bool initialized = false;
-  if (initialized) {
-    assert(new_chunk_monitor != NULL, "invariant");
-    return new_chunk_monitor;
-  }
-  assert(new_chunk_monitor == NULL, "invariant");
-  // read static field
-  HandleMark hm(thread);
-  static const char klass[] = "jdk/jfr/internal/JVM";
-  static const char field[] = "FILE_DELTA_CHANGE";
-  static const char signature[] = "Ljava/lang/Object;";
-  JavaValue result(T_OBJECT);
-  JfrJavaArguments field_args(&result, klass, field, signature, thread);
-  JfrJavaSupport::get_field_global_ref(&field_args, thread);
-  new_chunk_monitor = result.get_jobject();
-  initialized = new_chunk_monitor != NULL;
-  return new_chunk_monitor;
-}
-
-void JfrChunkSizeNotifier::notify() {
-  Thread* const thread = Thread::current();
-  JfrJavaSupport::notify_all(get_new_chunk_monitor(thread), thread);
-}
-
-void JfrChunkSizeNotifier::release_monitor() {
-  if (new_chunk_monitor != NULL) {
-    JfrJavaSupport::destroy_global_jni_handle(new_chunk_monitor);
-    new_chunk_monitor = NULL;
-  }
-}
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkSizeNotifier.hpp	Thu Dec 13 14:21:04 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2012, 2018, 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.
- *
- */
-
-#ifndef SHARE_VM_JFR_RECORDER_REPOSITORY_JFRRCHUNKSIZENOTIFIER_HPP
-#define SHARE_VM_JFR_RECORDER_REPOSITORY_JFRRCHUNKSIZENOTIFIER_HPP
-
-#include "memory/allocation.hpp"
-
-//
-// Responsible for notifications about current chunk size now exceeding threshold.
-// This is a means to initiate a chunk rotation on the basis of size written.
-//
-class JfrChunkSizeNotifier : AllStatic {
-  friend class JfrRecorder;
- private:
-  static size_t _chunk_size_threshold;
-  static void release_monitor();
- public:
-  static void set_chunk_size_threshold(size_t bytes);
-  static size_t chunk_size_threshold();
-  static void notify();
-};
-
-#endif // SHARE_VM_JFR_RECORDER_REPOSITORY_JFRRCHUNKSIZENOTIFIER_HPP
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp	Thu Dec 13 14:36:54 2018 +0100
@@ -28,7 +28,7 @@
 #include "jfr/recorder/jfrRecorder.hpp"
 #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
 #include "jfr/recorder/checkpoint/jfrMetadataEvent.hpp"
-#include "jfr/recorder/repository/jfrChunkSizeNotifier.hpp"
+#include "jfr/recorder/repository/jfrChunkRotation.hpp"
 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 #include "jfr/recorder/repository/jfrRepository.hpp"
 #include "jfr/recorder/service/jfrPostBox.hpp"
@@ -340,6 +340,7 @@
 void JfrRecorderService::open_new_chunk(bool vm_error) {
   assert(!_chunkwriter.is_valid(), "invariant");
   assert(!JfrStream_lock->owned_by_self(), "invariant");
+  JfrChunkRotation::on_rotation();
   MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
   if (!_repository.open_chunk(vm_error)) {
     assert(!_chunkwriter.is_valid(), "invariant");
@@ -535,8 +536,5 @@
 }
 
 void JfrRecorderService::evaluate_chunk_size_for_rotation() {
-  const size_t size_written = _chunkwriter.size_written();
-  if (size_written > JfrChunkSizeNotifier::chunk_size_threshold()) {
-    JfrChunkSizeNotifier::notify();
-  }
+  JfrChunkRotation::evaluate(_chunkwriter);
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java	Thu Dec 13 14:36:54 2018 +0100
@@ -516,4 +516,11 @@
      * @param emitAll emit all samples in old object queue
      */
     public native void emitOldObjectSamples(long cutoff, boolean emitAll);
+
+    /**
+     * Test if a chunk rotation is warranted.
+     *
+     * @return if it is time to perform a chunk rotation
+     */
+    public native boolean shouldRotateDisk();
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java	Thu Dec 13 14:21:04 2018 +0100
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java	Thu Dec 13 14:36:54 2018 +0100
@@ -427,19 +427,13 @@
     }
 
     private void periodicTask() {
+        if (!jvm.hasNativeJFR()) {
+            return;
+        }
         while (true) {
             synchronized (this) {
-                if (!jvm.hasNativeJFR()) {
-                    return;
-                }
-                if (currentChunk != null) {
-                    try {
-                        if (SecuritySupport.getFileSize(currentChunk.getUnfishedFile()) > Options.getMaxChunkSize()) {
-                            rotateDisk();
-                        }
-                    } catch (IOException e) {
-                        Logger.log(JFR_SYSTEM, WARN, "Could not check file size to determine chunk rotation");
-                    }
+                if (jvm.shouldRotateDisk()) {
+                    rotateDisk();
                 }
             }
             long minDelta = RequestEngine.doPeriodic();