From d992033439073d35877a2c0296fbd01ad5cbcb07 Mon Sep 17 00:00:00 2001 From: Mat Carter Date: Mon, 13 Nov 2023 20:56:58 +0000 Subject: [PATCH] 8317562: [JFR] Compilation queue statistics Reviewed-by: kvn --- src/hotspot/share/compiler/compileBroker.cpp | 13 +++ src/hotspot/share/compiler/compileBroker.hpp | 14 +++ src/hotspot/share/jfr/metadata/metadata.xml | 13 +++ .../periodic/jfrCompilerQueueUtilization.cpp | 91 +++++++++++++++++++ .../periodic/jfrCompilerQueueUtilization.hpp | 35 +++++++ .../share/jfr/periodic/jfrPeriodic.cpp | 5 + src/jdk.jfr/share/conf/jfr/default.jfc | 5 + src/jdk.jfr/share/conf/jfr/profile.jfc | 5 + .../TestCompilerQueueUtilization.java | 67 ++++++++++++++ test/lib/jdk/test/lib/jfr/EventNames.java | 1 + 10 files changed, 249 insertions(+) create mode 100644 src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.cpp create mode 100644 src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.hpp create mode 100644 test/jdk/jdk/jfr/event/compiler/TestCompilerQueueUtilization.java diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 22a9eb4dcaa..dce935a14d8 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -331,6 +331,10 @@ void CompileQueue::add(CompileTask* task) { _last = task; } ++_size; + ++_total_added; + if (_size > _peak_size) { + _peak_size = _size; + } // Mark the method as being in the compile queue. task->method()->set_queued_for_compilation(); @@ -487,6 +491,7 @@ void CompileQueue::remove(CompileTask* task) { _last = task->prev(); } --_size; + ++_total_removed; } void CompileQueue::remove_and_mark_stale(CompileTask* task) { @@ -516,6 +521,14 @@ CompileQueue* CompileBroker::compile_queue(int comp_level) { return nullptr; } +CompileQueue* CompileBroker::c1_compile_queue() { + return _c1_compile_queue; +} + +CompileQueue* CompileBroker::c2_compile_queue() { + return _c2_compile_queue; +} + void CompileBroker::print_compile_queues(outputStream* st) { st->print_cr("Current compiles: "); diff --git a/src/hotspot/share/compiler/compileBroker.hpp b/src/hotspot/share/compiler/compileBroker.hpp index 92c8628d18e..d136045102a 100644 --- a/src/hotspot/share/compiler/compileBroker.hpp +++ b/src/hotspot/share/compiler/compileBroker.hpp @@ -88,6 +88,9 @@ class CompileQueue : public CHeapObj { CompileTask* _first_stale; int _size; + int _peak_size; + uint _total_added; + uint _total_removed; void purge_stale_tasks(); public: @@ -96,6 +99,9 @@ class CompileQueue : public CHeapObj { _first = nullptr; _last = nullptr; _size = 0; + _total_added = 0; + _total_removed = 0; + _peak_size = 0; _first_stale = nullptr; } @@ -112,6 +118,9 @@ class CompileQueue : public CHeapObj { bool is_empty() const { return _first == nullptr; } int size() const { return _size; } + int get_peak_size() const { return _peak_size; } + uint get_total_added() const { return _total_added; } + uint get_total_removed() const { return _total_removed; } // Redefine Classes support void mark_on_stack(); @@ -302,6 +311,9 @@ public: int hot_count, CompileTask::CompileReason compile_reason, TRAPS); + static CompileQueue* c1_compile_queue(); + static CompileQueue* c2_compile_queue(); + private: static nmethod* compile_method(const methodHandle& method, int osr_bci, @@ -399,6 +411,8 @@ public: static CompileLog* get_log(CompilerThread* ct); + static int get_c1_thread_count() { return _compilers[0]->num_compiler_threads(); } + static int get_c2_thread_count() { return _compilers[1]->num_compiler_threads(); } static int get_total_compile_count() { return _total_compile_count; } static int get_total_bailout_count() { return _total_bailout_count; } static int get_total_invalidated_count() { return _total_invalidated_count; } diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 3a2a63276bf..7977b732eef 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -848,6 +848,19 @@ + + + + + + + + + + + + + diff --git a/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.cpp b/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.cpp new file mode 100644 index 00000000000..1ba31876cb9 --- /dev/null +++ b/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 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. + * + */ + +#include "precompiled.hpp" +#include "compiler/compileBroker.hpp" +#include "jfr/jfrEvents.hpp" +#include "jfr/periodic/jfrCompilerQueueUtilization.hpp" + +enum { + c1_compiler_queue_id = 1, + c2_compiler_queue_id = 2, + num_compiler_queues = 2 +}; + +typedef int (*GET_COMPILER_THREAD_COUNT)(); + +struct CompilerQueueEntry { + CompileQueue* compilerQueue; + u8 compiler_queue_id; + GET_COMPILER_THREAD_COUNT get_compiler_thread_count; + uint64_t added; + uint64_t removed; +}; + +// If current counters are less than previous, we assume the interface has been reset +// If no bytes have been either sent or received, we'll also skip the event +static uint64_t rate_per_second(uint64_t current, uint64_t old, const JfrTickspan& interval) { + assert(interval.value() > 0, "invariant"); + if (current <= old) { + return 0; + } + return ((current - old) * NANOSECS_PER_SEC) / interval.nanoseconds(); +} + +void JfrCompilerQueueUtilization::send_events() { + static CompilerQueueEntry compilerQueueEntries[num_compiler_queues] = { + {CompileBroker::c1_compile_queue(), c1_compiler_queue_id, &CompileBroker::get_c1_thread_count, 0, 0}, + {CompileBroker::c2_compile_queue(), c2_compiler_queue_id, &CompileBroker::get_c2_thread_count, 0, 0}}; + + const JfrTicks cur_time = JfrTicks::now(); + static JfrTicks last_sample_instant; + const JfrTickspan interval = cur_time - last_sample_instant; + for (int i = 0; i < num_compiler_queues; i ++) { + CompilerQueueEntry* entry = &compilerQueueEntries[i]; + if (entry->compilerQueue != nullptr) { + const uint64_t current_added = entry->compilerQueue->get_total_added(); + const uint64_t current_removed = entry->compilerQueue->get_total_removed(); + const uint64_t addedRate = rate_per_second(current_added, entry->added, interval); + const uint64_t removedRate = rate_per_second(current_removed, entry->removed, interval); + + EventCompilerQueueUtilization event; + event.set_compiler(entry->compiler_queue_id); + event.set_addedRate(addedRate); + event.set_removedRate(removedRate); + event.set_queueSize(entry->compilerQueue->size()); + event.set_peakQueueSize(entry->compilerQueue->get_peak_size()); + event.set_addedCount(current_added - entry->added); + event.set_removedCount(current_removed - entry->removed); + event.set_totalAddedCount(current_added); + event.set_totalRemovedCount(current_removed); + event.set_compilerThreadCount(entry->get_compiler_thread_count()); + event.commit(); + + entry->added = current_added; + entry->removed = current_removed; + } + + last_sample_instant = cur_time; + } +} \ No newline at end of file diff --git a/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.hpp b/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.hpp new file mode 100644 index 00000000000..7fe2e2c6aee --- /dev/null +++ b/src/hotspot/share/jfr/periodic/jfrCompilerQueueUtilization.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 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. + * + */ + +#ifndef SHARE_JFR_PERIODIC_JFRCOMPILERQUEUEUTILIZATION_HPP +#define SHARE_JFR_PERIODIC_JFRCOMPILERQUEUEUTILIZATION_HPP + +#include "memory/allStatic.hpp" + +class JfrCompilerQueueUtilization : public AllStatic { +public: + static void send_events(); +}; + +#endif // SHARE_JFR_PERIODIC_JFRCOMPILERQUEUEUTILIZATION_HPP \ No newline at end of file diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index 9e1e9625457..764b7e122ec 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -36,6 +36,7 @@ #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/objectCountEventSender.hpp" #include "jfr/jfrEvents.hpp" +#include "jfr/periodic/jfrCompilerQueueUtilization.hpp" #include "jfr/periodic/jfrFinalizerStatisticsEvent.hpp" #include "jfr/periodic/jfrModuleEvent.hpp" #include "jfr/periodic/jfrOSInterface.hpp" @@ -221,6 +222,10 @@ TRACE_REQUEST_FUNC(ThreadCPULoad) { JfrThreadCPULoadEvent::send_events(); } +TRACE_REQUEST_FUNC(CompilerQueueUtilization) { + JfrCompilerQueueUtilization::send_events(); +} + TRACE_REQUEST_FUNC(NetworkUtilization) { JfrNetworkUtilization::send_events(); } diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index 6b0aa1724c4..38a3b9cc51c 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -663,6 +663,11 @@ 5 s + + true + 10 s + + true beginChunk diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index 79ce390052a..7294d077e2a 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -663,6 +663,11 @@ 5 s + + true + 5 s + + true beginChunk diff --git a/test/jdk/jdk/jfr/event/compiler/TestCompilerQueueUtilization.java b/test/jdk/jdk/jfr/event/compiler/TestCompilerQueueUtilization.java new file mode 100644 index 00000000000..081cb5296d5 --- /dev/null +++ b/test/jdk/jdk/jfr/event/compiler/TestCompilerQueueUtilization.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 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. + */ + +package jdk.jfr.event.compiler; + +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.hasJFR + * @requires vm.compMode!="Xint" + * @library /test/lib + * @run main/othervm jdk.jfr.event.compiler.TestCompilerQueueUtilization + */ +public class TestCompilerQueueUtilization { + private final static String EVENT_NAME = EventNames.CompilerQueueUtilization; + + public static void main(String[] args) throws Exception { + try (Recording recording = new Recording()) { + recording.enable(EVENT_NAME); + recording.start(); + recording.stop(); + + List events = Events.fromRecording(recording); + Events.hasEvents(events); + for (RecordedEvent event : events) { + System.out.println("Event:" + event); + Events.assertField(event, "compiler").notEmpty(); + Events.assertField(event, "addedRate").atLeast(0L); + Events.assertField(event, "removedRate").atLeast(0L); + Events.assertField(event, "queueSize").atLeast(0L); + Events.assertField(event, "peakQueueSize").atLeast(0L); + Events.assertField(event, "addedCount").atLeast(0L); + Events.assertField(event, "removedCount").atLeast(0L); + Events.assertField(event, "totalAddedCount").atLeast(0L); + Events.assertField(event, "totalRemovedCount").atLeast(0L); + Events.assertField(event, "compilerThreadCount").atLeast(0); + } + } + } +} diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java index fd0dcc6895a..2ce34ed5b5a 100644 --- a/test/lib/jdk/test/lib/jfr/EventNames.java +++ b/test/lib/jdk/test/lib/jfr/EventNames.java @@ -160,6 +160,7 @@ public class EventNames { public static final String CompilerPhase = PREFIX + "CompilerPhase"; public static final String CompilationFailure = PREFIX + "CompilationFailure"; public static final String CompilerInlining = PREFIX + "CompilerInlining"; + public static final String CompilerQueueUtilization = PREFIX + "CompilerQueueUtilization"; public static final String CompilerStatistics = PREFIX + "CompilerStatistics"; public static final String CompilerConfiguration = PREFIX + "CompilerConfiguration"; public static final String CodeCacheStatistics = PREFIX + "CodeCacheStatistics";