-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
[GR-51307] Add GC NotificationEmitter Support #9799
base: master
Are you sure you want to change the base?
Conversation
3377f06
to
5e2e82e
Compare
5e2e82e
to
1923bf4
Compare
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.
Thanks for the PR, I added a larger number of comments.
private volatile GcInfo gcInfo; | ||
private long seqNumber = 0; | ||
|
||
private synchronized GcInfoBuilder getGcInfoBuilder() { |
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 don't think that this need to be synchronized
(only called by the service thread).
Please move private helper methods to a place that is below their caller (they are not super important, so they are usually not the first code that someone who opens that class wants to see).
private synchronized GcInfoBuilder getGcInfoBuilder() { | ||
if (gcInfoBuilder == null) { | ||
Target_com_sun_management_internal_GcInfoBuilder gib = new Target_com_sun_management_internal_GcInfoBuilder(this, getMemoryPoolNames()); | ||
gcInfoBuilder = SubstrateUtil.cast(gib, GcInfoBuilder.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.
You can avoid this cast if you use Target_com_sun_management_internal_GcInfoBuilder
instead of GcInfoBuilder
everywhere (including in the constructor of Target_com_sun_management_GcInfo
).
|
||
@Override | ||
public GcInfo getLastGcInfo() { | ||
return gcInfo; |
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 returns the last gcInfo
that was processed by the service thread (i.e., new information will be available with a delay). Is the behavior the same on HotSpot or do they always report up-to-date data?
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.
Oh that's a good point. And it's worse if the queue has more items in it. It looks like Hotspot always returns info from the most recent GC. I'll change this method to do the same.
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've fixed the approach here by always caching the GC info during the collection. This is basically what Hotspot is doing too.
} | ||
|
||
// Number of GC threads. | ||
Object[] extAttribute = new Object[]{Integer.valueOf(1)}; |
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 this particular case, I would prefer something like the following, as it makes things clearer and more readable:
Object[] extAttribute = new Object[1];
extAttribute[0] = 1; // number of GC threads
import org.graalvm.word.UnsignedWord; | ||
|
||
public class ServiceSupport { | ||
private GcNotifier gcNotifier; |
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 field and serviceThread
can be final.
* We don't need to drain all requests since signals queue at the semaphore level. The rest | ||
* of the requests will be handled in subsequent calls to this method by the sevice thread. | ||
*/ | ||
if (!updateCurrentRequest()) { |
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 adapt this logic once you switch to VMMutex
and VMCondition
.
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 is now handled by checking NotificationThread.hasRequests()
before blocking in the notification thread loop.
* This class is the dedicated thread that handles services. For now, the only service is GC | ||
* notifications. | ||
*/ | ||
public class ServiceThread extends Thread { |
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.
Does HotSpot use the service thread or a separate notification thread for the GC notifications?
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.
Hotspot uses NotificationThread
, which is different than ServiceThread
. Should I rename this class "NotificationThread" instead? Unless we plan to have a single dedicated thread handle service and notifications.
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.
Renamed everything to notification*
|
||
@Platforms(Platform.HOSTED_ONLY.class) | ||
@SuppressWarnings("this-escape") | ||
public ServiceThread(GcNotifier gcNotifier) { |
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 set a name for this thread, and potentially also a thread group (please check in the HotSpot code).
* Use the data taken from the request queue to populate MemoryUsage. The service thread calls | ||
* this method. | ||
*/ | ||
public void createNotification(GcNotificationRequest request) { |
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.
Parts of this code are probably based on OpenJDK code. If so, please annotate with @BasedOnJDKFile
.
* questions. | ||
*/ | ||
|
||
package com.oracle.svm.core.genscavenge.service; |
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 everything in this package to a sub package in the GC independent project com.oracle.svm.core
.
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 tried doing that originally, but it seems I cannot import from com.oracle.svm.core.genscavenge
from inside com.oracle.svm.core
. Is there a way to work around this?
The build error:
error: package com.oracle.svm.core.genscavenge does not exist
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 will need to split the implementation into a GC independent and a GC-specific part. This will also make it easier to implement this for all Native Image GCs in the future:
- GC independent parts in
com.oracle.svm.core
: notification thread, notification logic, and all the GC independent logic that accesses the memory pools. You will probably need introduce an interface and implementation that interface on the GC-specific side. - GC specific parts in
com.oracle.svm.core.genscavenge
: essentially everything that would be different for a completely different GC implementation (e.g., the logic inGenScavengeMemoryPoolMXBeans
, how many memory pools a GC uses, or how the memory pools are named)
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 put the files into com.oracle.svm.core.notification
and com.oracle.svm.core.gc
(the naming could maybe be improved).
com.oracle.svm.core.gc
contains the interface MemoryPoolMXBeansProvider
for accessing GC-specific memory pool info.
I also put AbstractGarbageCollectorMXBean
inside com.oracle.svm.core.gc
. Different GCs can override methods like gcThreadCount()
and isIncremental()
so that the notification infrastructure knows how to handle notifications for different collectors.
Thank you for the review @christianhaeubl. I think I've addressed all your comments. Please have another look when you have time. Thanks! |
Thanks. I started integrating this PR. I will let you know if I run into any major issues. |
Thanks @christianhaeubl ! |
Summary
This PR adds support for the emission of GC notifications from GC MXBeans. Previously, SubstratVM's GC MXBeans (
CompleteGarbageCollectorMXBean
andIncrementalGarbageCollectorMXBean
) implementedNotificationEmitter
, but actually did not support notifications.Details
A new feature
ServiceFeature
has been added. Use--enable-monitoring=gcnotif
to include the feature at build time and add support for GC notifications.The ImageSingleton
ServiceSupport
starts up a dedicated service thread which asynchronously handles creating and sending notifications. Notification "requests" are created during GC safepoints. They temporarily hold the information later needed to create and send GC notifications. During the GC safepoint, the thread executing the VM operation enqueues a request inGcNotifier
and signals the service thread that a request is ready. That process should be relatively quick and allocation free. Once the safepoint is over, the service thread uses the queued requests to create notifications that are sent by the appropriate GC MXBean.The new classes
GcNotifier
andServiceThread
are meant to serve almost the same purposes as theGCNotifier
andServiceThread
classes in Hotspot respectively.The various GC MXBeans now extend
AbstractGarbageCollectorMXBean
which contains the code for creating and sending notifications from request data. This class serves a similar purpose tocom.sun.management.internal.GarbageCollectorExtImpl
. Additionally, this class extendssun.management.NotificationEmitterSupport
from which the listener registration/deregistration logic is reused.Other notes
I'm not sure about the naming of
ServiceSupport
andServiceFeature
. MaybeNotificationSupport
makes more sense? I decided on the "service" prefix because, in Hotspot, the GC notification code is in the /hotspot/share/services directory. Also, maybe we will want to add other services in the future.Related Issues: #8237