-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of GC phase pause events #4272
Conversation
JfrNativeEventWriter.putEventThread(data); | ||
JfrNativeEventWriter.putLong(data, phase.getGCEpoch().rawValue()); | ||
|
||
int len = phase.getName().getLength(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code below can be replaced with JfrNativeEventWriter.putString
.
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; | ||
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE; | ||
|
||
final class NativeStringConversion { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class should be unnecessary.
* NativeString stores java.lang.String content in native memory | ||
*/ | ||
@RawStructure | ||
interface NativeString extends PointerBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface should be unnecessary.
case 4: | ||
return JfrEvents.GCPhasePauseLevel4Event; | ||
default: | ||
VMError.shouldNotReachHere("At most " + MAX_PHASE_LEVEL + " levels"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw VMError...
avoids the unnecessary return.
* Therefore, we need to keep the states on stack or in native memory. | ||
*/ | ||
@RawStructure | ||
public interface JfrGCPausePhase extends PointerBase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface should be unnecessary.
@@ -207,6 +209,9 @@ private boolean collectImpl(GCCause cause, long requestingNanoTime, boolean forc | |||
precondition(); | |||
|
|||
NoAllocationVerifier nav = noAllocationVerifier.open(); | |||
|
|||
JfrGCPausePhase phase = StackValue.get(JfrGCPausePhase.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that a large portion of this PR is unnecessary. I don't think that there is any need for extra data structures:
- the GC epoch can be queried at any time via getCollectionEpoch()
- the start ticks can be stored in a local
- the level can be a constant
- the phase name can be a String constant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Are constant strings guaranteed in unmovable partition of heap in binary image? I introduced NativeString, not because of this PR, but if I want to generate per-worker events during, e.g. object evacuation phase, I am not sure, but unlikely, there are barriers for accessing the phase names on GC path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constant strings are located the image heap and won't be touched by the GC, so they can be used safely. Per-worker events would still use the same constant Strings (only the data in the eventThread
field of the JFR events would be different).
@@ -137,6 +142,21 @@ public void afterThreadExit(IsolateThread isolateThread, Thread javaThread) { | |||
nativeBuffer.set(isolateThread, WordFactory.nullPointer()); | |||
} | |||
|
|||
public void pushPausePhaseLevel() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In GCImpl
, it should be possible to directly use constant instead of a counter for the levels. If that is not feasible for some reason, please add the level as a field to JfrGCEventSupport
and use that instead of the thread local.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
import com.oracle.svm.core.jfr.SubstrateJVM; | ||
import com.oracle.svm.core.util.VMError; | ||
|
||
public abstract class JfrGCEventSupport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this class to the GC project as only that GC will use this file. There shouldn't be any need to register this class as an ImageSingleton (you can add a new field to GCImpl
instead).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean moving it to com.oracle.svm.core.genscavenge
? Is it the only GC that graal plans to support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, com.oracle.svm.core.genscavenge
.
For now, this is the only GC that will use this particular implementation to trigger JFR events.
|
||
public abstract void emitGCPausePhaseEvent(UnsignedWord gcEpoch, String name, long startTicks); | ||
|
||
public static class Unsupported extends JfrGCEventSupport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This extra dummy implementation shouldn't be necessary. You can directly check in each relevant methods if the JFR support is enabled or not (see JfrEnabled.get()
). This will get optimized at image build time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I thought it is a runtime flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JfrEnabled.get()
is annotated with @Fold
and this annotation ensures that the method is optimized away and replaced with a constant during the image build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good, please squash your commits if possible. I will then integrate them into master.
870990e
to
23192ad
Compare
Done. The failed tests do not seem to relate to this PR. Thanks! |
23192ad
to
a46c6be
Compare
All clean now. |
This PR was already merged to master - seems that the graalvmbot didn't realize that. |
870990e was the commit I believe. |
Please review this patch that implements GC pause phase events.
GC pause phase events are emitted during GC phase changes at GC pause. To match hotspot implementation, there can be maximum 5 level (0 - 4) of nesting phases
The sample events: