Skip to content
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-44559] Finish ThreadMXBean implementation for Native Image. #8430

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

graalvmbot
Copy link
Collaborator

@graalvmbot graalvmbot commented Feb 22, 2024

See #7945. Closes #6101.

Copy link
Member

@christianhaeubl christianhaeubl left a 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 few comments and questions.

I did not do a detailed review yet but I had a brief look at the HotSpot code for the same functionality and it uses a completely different approach (thread info is dumped during a VM operation). I think we will need something similar to avoid a large performance impact.

@@ -91,6 +94,42 @@ public final class Target_java_lang_Thread {
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClass = ThreadData.class)//
UnacquiredThreadData threadData;

@Inject //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
long lastStartedWaiting = -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a suffix to all fields that store a value in milli- or nanoseconds (e.g., lastStartedWaitingMs)

@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
long lastStartedWaiting = -1;

@Inject //
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please only inject a single new object field into the Thread object. This object field can then point to an object that holds all the other fields.

@@ -1075,8 +1075,10 @@ public static int getThreadStatus(Thread thread) {
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public static void setThreadStatus(Thread thread, int threadStatus) {
assert !isVirtual(thread);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does HotSpot only support contention monitoring for non-virtual threads?


@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private static void handleContentionWhenEnabled(Target_java_lang_Thread targetThread, int threadStatus) {
switch (threadStatus) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also check for all other possible thread status values and add a default case. The new cases should either throw an error or do nothing.


@Inject //
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
long timeBlocked = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to enable and disable contention monitoring at run-time? If so, what should happen with outdated values if contention monitoring gets enabled, disabled, and enabled again.

*
* @return the owner thread
*/
@Alias
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods that are only annotated with @Alias must not have an implementation.

public record MonitorInfo(Object originalObject, int stacksize) {
}

public static void addThreadMonitor(Object originalObject) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, you are calling this method unconditionally. This method has a large performance impact, so this definitely needs to be called conditionally.

@Substitute()
protected void setExclusiveOwnerThread(Thread thread) {
if (thread == null && exclusiveOwnerThread != null) {
JavaThreads.JMXMonitoring.removeThreadLock(exclusiveOwnerThread,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does HotSpot track contentions for ReentrantLocks?

return state;
}

public static ThreadInfo getThreadInfo(Thread thread, int maxDepth,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should this method return if the thread is no longer
a. alive
b. blocked

I think a lot of corner cases are missing here.

Blocker blocker = getBlockerInfo(thread);
StackTraceElement[] stackTrace = getStackTrace(thread, maxDepth);
LockedMonitors lockedMonitors = getLockedMonitors(thread, stackTrace.length);
boolean inNative = stackTrace.length > 0 && stackTrace[0].isNativeMethod();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct - you would need to access the VM-internal thread state of the isolate thread but this isn't accessible easily for threads other than the current thread.

@fniephaus
Copy link
Member

@smthelusive could you please take a look at @christianhaeubl's comments?

@smthelusive
Copy link

Hi @christianhaeubl, thank you for the review.
Given what you said that the whole approach should be different, how should I proceed with this PR? Does it make sense to continue polishing this solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OCA Verified All contributors have signed the Oracle Contributor Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[GR-44559] Finish ThreadMXBean implementation for Native Image.
4 participants