Skip to content
This repository has been archived by the owner on Apr 24, 2023. It is now read-only.

Commit

Permalink
8298175: JFR: Common timestamp for periodic events
Browse files Browse the repository at this point in the history
Reviewed-by: dholmes, mgronlun
  • Loading branch information
egahlin committed Dec 8, 2022
1 parent 94575d1 commit 9353899
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 23 deletions.
10 changes: 9 additions & 1 deletion make/src/classes/build/tools/jfr/GenerateJfrFiles.java
Expand Up @@ -573,9 +573,13 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro
out.write("#include \"jfrfiles/jfrEventIds.hpp\"");
out.write("#include \"memory/allocation.hpp\"");
out.write("");
out.write("enum PeriodicType {BEGIN_CHUNK, INTERVAL, END_CHUNK};");
out.write("");
out.write("class JfrPeriodicEventSet : public AllStatic {");
out.write(" public:");
out.write(" static void requestEvent(JfrEventId id) {");
out.write(" static void requestEvent(JfrEventId id, jlong timestamp, PeriodicType periodicType) {");
out.write(" _timestamp = Ticks(timestamp);");
out.write(" _type = periodicType;");
out.write(" switch(id) {");
out.write(" ");
for (TypeElement e : metadata.getPeriodicEvents()) {
Expand All @@ -595,6 +599,10 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro
out.write(" static void request" + e.name + "(void);");
out.write("");
}
out.write(" static Ticks timestamp(void);");
out.write(" static Ticks _timestamp;");
out.write(" static PeriodicType type(void);");
out.write(" static PeriodicType _type;");
out.write("};");
out.write("");
out.write("#endif // INCLUDE_JFR");
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/jfr/jni/jfrJniMethod.cpp
Expand Up @@ -238,8 +238,8 @@ JVM_ENTRY_NO_ENV(void, jfr_mark_chunk_final(JNIEnv * env, jobject jvm))
JfrRepository::mark_chunk_final();
JVM_END

JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when))
JfrPeriodicEventSet::requestEvent((JfrEventId)eventTypeId);
JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong event_type_id, jlong timestamp, jlong periodic_type))
JfrPeriodicEventSet::requestEvent((JfrEventId)event_type_id, timestamp, static_cast<PeriodicType>(periodic_type));
return thread->has_pending_exception() ? JNI_FALSE : JNI_TRUE;
JVM_END

Expand Down
12 changes: 12 additions & 0 deletions src/hotspot/share/jfr/periodic/jfrPeriodic.cpp
Expand Up @@ -81,6 +81,18 @@
*/
#define TRACE_REQUEST_FUNC(id) void JfrPeriodicEventSet::request##id(void)

// Timestamp to correlate events in the same batch/generation
Ticks JfrPeriodicEventSet::_timestamp;
PeriodicType JfrPeriodicEventSet::_type;

Ticks JfrPeriodicEventSet::timestamp(void) {
return _timestamp;
}

PeriodicType JfrPeriodicEventSet::type(void) {
return _type;
}

TRACE_REQUEST_FUNC(JVMInformation) {
ResourceMark rm;
EventJVMInformation event;
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/utilities/ticks.hpp
Expand Up @@ -231,6 +231,7 @@ class TimeInstant : public Rep<TimeSource> {
friend class GranularTimer;
friend class ObjectSample;
friend class EventEmitter;
friend class JfrPeriodicEventSet;
// GC unit tests
friend class TimePartitionsTest;
friend class GCTimerTest;
Expand Down
4 changes: 2 additions & 2 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
Expand Up @@ -118,11 +118,11 @@ private JVM() {
* @param eventTypeId type id
*
* @param timestamp commit time for event
* @param when when it is being done {@link Periodic.When}
* @param periodicType when it is being done {@link PeriodicType.When}
*
* @return true if the event was committed
*/
public native boolean emitEvent(long eventTypeId, long timestamp, long when);
public native boolean emitEvent(long eventTypeId, long timestamp, long periodicType);

/**
* Return a list of all classes deriving from {@link jdk.internal.event.Event}
Expand Down
37 changes: 19 additions & 18 deletions src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2022, 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
Expand Down Expand Up @@ -39,6 +39,9 @@
import jdk.jfr.EventType;

public final class RequestEngine {
enum PeriodicType {
BEGIN_CHUNK, INTERVAL, END_CHUNK
}

private static final JVM jvm = JVM.getJVM();
private static final ReentrantLock lock = new ReentrantLock();
Expand All @@ -62,13 +65,13 @@ private RequestHook(@SuppressWarnings("removal") AccessControlContext acc, Platf
this(null, eventType, null);
}

private void execute() {
private void execute(long timestamp, PeriodicType periodicType) {
try {
if (accessControllerContext == null) { // native
if (type.isJDK()) {
hook.run();
} else {
emitJVMEvent(type);
emitJVMEvent(type, timestamp, periodicType);
}
if (Logger.shouldLog(LogTag.JFR_SYSTEM, LogLevel.DEBUG)) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Executed periodic hook for " + type.getLogName());
Expand All @@ -82,13 +85,13 @@ private void execute() {
}
}

private void emitJVMEvent(PlatformEventType type) {
private void emitJVMEvent(PlatformEventType type, long timestamp, PeriodicType periodicType) {
try {
// There should only be one thread in native at a time.
// ReentrantLock is used to avoid JavaMonitorBlocked event
// from synchronized block.
lock.lock();
jvm.emitEvent(type.getId(), JVM.counterTime(), 0);
jvm.emitEvent(type.getId(), timestamp, periodicType.ordinal());
} finally {
lock.unlock();
}
Expand Down Expand Up @@ -183,35 +186,33 @@ static void addHooks(List<RequestHook> newEntries) {
}

static void doChunkEnd() {
doChunk(x -> x.isEndChunk());
doChunk(x -> x.isEndChunk(), PeriodicType.END_CHUNK);
}

static void doChunkBegin() {
doChunk(x -> x.isBeginChunk());
doChunk(x -> x.isBeginChunk(), PeriodicType.BEGIN_CHUNK);
}

private static void doChunk(Predicate<PlatformEventType> predicate) {
private static void doChunk(Predicate<PlatformEventType> predicate, PeriodicType type) {
long timestamp = JVM.counterTime();
for (RequestHook requestHook : entries) {
PlatformEventType s = requestHook.type;
if (s.isEnabled() && predicate.test(s)) {
requestHook.execute();
requestHook.execute(timestamp, type);
}
}
}

static long doPeriodic() {
return run_requests(entries);
return run_requests(entries, JVM.counterTime());
}

// code copied from native impl.
private static long run_requests(Collection<RequestHook> entries) {
private static long run_requests(Collection<RequestHook> entries, long eventTimestamp) {
long last = lastTimeMillis;
// Bug 9000556 - current time millis has rather lame resolution
// The use of os::elapsed_counter() is deliberate here, we don't
// want it exchanged for os::ft_elapsed_counter().
// Keeping direct call os::elapsed_counter() here for reliable
// real time values in order to decide when registered requestable
// events are due.
// The interval for periodic events is typically at least 1 s, so
// System.currentTimeMillis() is sufficient. JVM.counterTime() lacks
// unit and has in the past been more unreliable.
long now = System.currentTimeMillis();
long min = 0;
long delta = 0;
Expand Down Expand Up @@ -249,7 +250,7 @@ private static long run_requests(Collection<RequestHook> entries) {
// Bug 9000556 - don't try to compensate
// for wait > period
r_delta = 0;
he.execute();
he.execute(eventTimestamp, PeriodicType.INTERVAL);
}

// calculate time left
Expand Down

0 comments on commit 9353899

Please sign in to comment.