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

Add some JFR event tests #4932

Merged
merged 17 commits into from
Jan 31, 2023
Merged

Conversation

roberttoyonaga
Copy link
Collaborator

@roberttoyonaga roberttoyonaga commented Sep 12, 2022

Add some tests for recently added JFR events:

  • jdk.JavaMonitorEnter
  • jdk.JavaMonitorWait
  • jdk.ThreadSleep

Each test generates the desired events to test, creates a JFR snapshot, and inspects the snapshot. There are 4 jdk.JavaMonitorWait tests that each cover a different case (time out, interruption, notify all, notify).

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Sep 12, 2022
@fniephaus fniephaus added this to the 23.0 milestone Sep 15, 2022
@christianwimmer christianwimmer requested review from christianhaeubl and peter-hofer and removed request for christianwimmer September 22, 2022 14:41
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 working on test cases for certain JFR events.

In a lot of your test cases, you try to use Thread.sleep() to ensure that multiple threads do something in a particular order. An approach like does not work reliably (especially if the machine has high load) and is therefore neither feasible for production code nor for test cases. You will need to switch to some kind of proper synchronization (e.g., ReentrantLock or a spin lock in case that you want to avoid that certain JFR events are emitted).

simpleNotifyName = tn.getName();

tw.start();
Thread.sleep(50);
Copy link
Member

Choose a reason for hiding this comment

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

This also won't work reliably.

if (!struct.<RecordedClass> getValue("monitorClass").getName().equals(Helper.class.getName())) {
continue;
}
assertTrue("Event is wrong duration.", isGreaterDuration(Duration.ofMillis(MILLIS), event.getDuration()));
Copy link
Member

Choose a reason for hiding this comment

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

This won't work reliably at the moment, see comments below.


public synchronized void consume() throws InterruptedException {
// give the producers a headstart so they can start waiting
wait(MILLIS);
Copy link
Member

Choose a reason for hiding this comment

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

This won't work reliably.

notifierName = unheardNotifierThread.getName();

timeoutThread.start();
Thread.sleep(10);
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't work reliably.

if (!eventThread.equals(sleepingThreadName)) {
continue;
}
if (!isEqualDuration(event.getDuration(), Duration.ofMillis(MILLIS))) {
Copy link
Member

Choose a reason for hiding this comment

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

This won't work reliably.

@roberttoyonaga
Copy link
Collaborator Author

Thank you for the review Christian! I have updated the thread synchronization to be more reliable and removed the cases where sleeping is used to try to enforce ordering. Please let me know if there are still issues.

@roberttoyonaga roberttoyonaga requested review from christianhaeubl and removed request for peter-hofer October 7, 2022 19:48
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 changes this already improves the situation. However, there is still one problematic pattern: querying Thread.getState() in a loop is unreliable because it doesn't tell the reason why a thread is blocked or waiting. So, the following can happen:

  • Thread A calls Thread.getState() on thread B and checks if thread B is blocked or waiting.
  • Thread B blocks or waits in JDK-internal code while the thread is being started (i.e. before it even reaches run()).
  • Thread A sees the changed thread status and assumes that thread B is blocked at the right position in run().

Thread.sleep(10);
}
blockedAtCritical = true;
helper.doWork();
Copy link
Collaborator Author

@roberttoyonaga roberttoyonaga Oct 11, 2022

Choose a reason for hiding this comment

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

Is setting/checking of blockedAtCritical enough to guarantee the thread is blocking where we expect it to? I don't think it's possible to use the same pattern I've updated the monitor wait tests to. This is because monitor enter events don't seem to be emitted upon re-entry to synchronized blocks.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, this should work. The name blockedAtCritical is a bit misleading though because the thread is not blocked yet (thread B just reached a point where thread A can use thread.getState() reliably to determine if thread B is blocked).

Thread.sleep(10);
}
blockedAtCritical = true;
helper.doWork();
Copy link
Member

Choose a reason for hiding this comment

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

Yes, this should work. The name blockedAtCritical is a bit misleading though because the thread is not blocked yet (thread B just reached a point where thread A can use thread.getState() reliably to determine if thread B is blocked).

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, your PR will be merged to master in the next couple days.

@graalvmbot graalvmbot merged commit c14576f into oracle:master Jan 31, 2023
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.

4 participants