Skip to content

Commit

Permalink
Merge pull request #20834 from tajila/jfrtest
Browse files Browse the repository at this point in the history
Add JFR test cases
  • Loading branch information
babsingh authored Dec 16, 2024
2 parents 7c6a848 + 49af1c9 commit 91d6140
Show file tree
Hide file tree
Showing 8 changed files with 296 additions and 2,182 deletions.
3 changes: 3 additions & 0 deletions runtime/vm/JFRConstantPoolTypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ class VM_JFRConstantPoolTypes {
if (NULL != jfrConstantEvents) {
PORT_ACCESS_FROM_JAVAVM(vm);
j9mem_free_memory(jfrConstantEvents->JVMInfoEntry.jvmArguments);
jfrConstantEvents->JVMInfoEntry.jvmArguments = NULL;
}
}

Expand Down Expand Up @@ -1016,6 +1017,7 @@ class VM_JFRConstantPoolTypes {
if (NULL != jfrConstantEvents) {
PORT_ACCESS_FROM_JAVAVM(vm);
j9mem_free_memory(jfrConstantEvents->CPUInfoEntry.description);
jfrConstantEvents->CPUInfoEntry.description = NULL;
}
}

Expand Down Expand Up @@ -1099,6 +1101,7 @@ class VM_JFRConstantPoolTypes {
if (NULL != jfrConstantEvents) {
PORT_ACCESS_FROM_JAVAVM(vm);
j9mem_free_memory(jfrConstantEvents->OSInfoEntry.osVersion);
jfrConstantEvents->OSInfoEntry.osVersion = NULL;
}
}

Expand Down
1 change: 1 addition & 0 deletions runtime/vm/jfr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ initializeJFR(J9JavaVM *vm, BOOLEAN lateInit)
if (NULL == vm->jfrState.constantEvents) {
goto fail;
}
memset(vm->jfrState.constantEvents, 0, sizeof(JFRConstantEvents));

/* Allocate global data. */
buffer = (U_8*)j9mem_allocate_memory(J9JFR_GLOBAL_BUFFER_SIZE, OMRMEM_CATEGORY_VM);
Expand Down
2 changes: 1 addition & 1 deletion test/functional/cmdLineTests/jfr/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
<contains string="${TEST_FLAG}" substring="JFR" />
<!-- For the time being, JFR tests are only limited to JDK17+. -->
<not>
<matches string="${JDK_VERSION}" pattern="^(8|9|1[0-6])$$" />
<matches string="${JDK_VERSION}" pattern="^(8|9)$$" />
</not>
</and>
</condition>
Expand Down
15 changes: 15 additions & 0 deletions test/functional/cmdLineTests/jfr/jfr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,19 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.TriggerExecutionSample</command>
<return type="success" value="0" />
</test>
<test id="runWorkload - approx 30seconds">
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad</command>
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
<output type="failure" caseSensitive="yes" regex="no">Exception</output>
</test>
<test id="runWorkload 2 - approx 2mins">
<command>$EXE$ -XX:+FlightRecorder --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.WorkLoad 200 20000 200</command>
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
<output type="failure" caseSensitive="yes" regex="no">Exception</output>
</test>
<test id="runWorkload 2 - approx 2mins">
<command>$EXE$ --add-exports java.base/com.ibm.oti.vm=ALL-UNNAMED -cp $RESJAR$ org.openj9.test.VMAPITest</command>
<output type="success" caseSensitive="yes" regex="no">All runs complete.</output>
<output type="failure" caseSensitive="yes" regex="no">Failed</output>
</test>
</suite>
2,180 changes: 0 additions & 2,180 deletions test/functional/cmdLineTests/jfr/metadata.blob

This file was deleted.

2 changes: 1 addition & 1 deletion test/functional/cmdLineTests/jfr/playlist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
</impls>
<!-- For the time being, JFR tests are only limited to JDK17+. -->
<versions>
<version>17+</version>
<version>11+</version>
</versions>
<features>
<feature>JFR:required</feature>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright IBM Corp. and others 2024
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*/
package org.openj9.test;

import com.ibm.oti.vm.VM;

public class VMAPITest {
public static void main(String[] args) throws Throwable {
final WorkLoad workLoad = new WorkLoad(200, 20000, 200);

if (VM.isJFRRecordingStarted()) {
System.out.println("Failed should not be recording.");
return;
}

Thread app = new Thread(() -> {
workLoad.runWork();
});
app.start();

for (int i = 0; i < 15; i++) {
Thread.sleep(100);

if (VM.startJFR() != 0) {
System.out.println("Failed to start.");
return;
}

if (!VM.isJFRRecordingStarted()) {
System.out.println("Failed to record.");
return;
}

if (!VM.setJFRRecordingFileName("sample" + i + ".jfr")) {
System.out.println("Failed to set name.");
return;
}

Thread.sleep(1000);
VM.jfrDump();
VM.stopJFR();

if (VM.isJFRRecordingStarted()) {
System.out.println("Failed to stop recording.");
return;
}
}
}
}
207 changes: 207 additions & 0 deletions test/functional/cmdLineTests/jfr/src/org/openj9/test/WorkLoad.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
/*
* Copyright IBM Corp. and others 2024
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*/
package org.openj9.test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.LockSupport;

public class WorkLoad {
private int numberOfThreads;
private int sizeOfNumberList;
private int repeats;

public static double average;
public static double stdDev;

public WorkLoad(int numberOfThreads, int sizeOfNumberList, int repeats) {
this.numberOfThreads = numberOfThreads;
this.sizeOfNumberList = sizeOfNumberList;
this.repeats = repeats;
}

public static void main(String[] args) {
int numberOfThreads = 100;
int sizeOfNumberList = 10000;
int repeats = 50;

if (args.length > 0) {
numberOfThreads = Integer.parseInt(args[0]);
}

if (args.length > 1) {
sizeOfNumberList = Integer.parseInt(args[1]);
}

if (args.length > 2) {
repeats = Integer.parseInt(args[2]);
}

WorkLoad workload = new WorkLoad(numberOfThreads, sizeOfNumberList, repeats);
workload.runWork();
}

public void runWork() {
final AtomicLong completionCount = new AtomicLong(0);
Thread threads[] = new Thread[numberOfThreads];

for (int i = 0; i < numberOfThreads; i++) {
threads[i] = new Thread(() -> {
workload();
completionCount.incrementAndGet();
});
threads[i].start();
}

while (completionCount.get() < numberOfThreads) {
System.out.println(completionCount.get() + " / " + numberOfThreads + " complete.");
try {
Thread.sleep(numberOfThreads * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("All runs complete. " + average + " : " + stdDev);
}

private void workload() {
for (int i = 0; i < repeats; i++) {
generateAnonClasses();
generateTimedPark();
generateTimedSleep();
generateTimedWait();
throwThrowables();
burnCPU();
}
}

private void recursiveFucntion(int depth) {
if (0 == depth) {
return;
}

recursiveFucntion(depth - 1);
}

private void recursiveFucntionWithCallable(int depth, Callable<?> c) {
if (0 == depth) {
try {
c.call();
} catch (Exception e) {}
return;
}

recursiveFucntionWithCallable(depth - 1, c);
}

private void generateAnonClasses() {
Callable<?> c = () -> {
recursiveFucntion(30);
return 0;
};

try {
c.call();
} catch (Exception e) {}
}

private void generateTimedPark() {
recursiveFucntionWithCallable(10, () -> {
LockSupport.parkNanos(100000);
return 0;
});
}

private void generateTimedSleep() {
recursiveFucntionWithCallable(10, () -> {
Thread.sleep(100);
return 0;
});
}

private void generateTimedWait() {
recursiveFucntionWithCallable(10, () -> {
Object o = new Object();

synchronized(o) {
o.wait(100);
}

return 0;
});
}

private void burnCPU() {
ArrayList<Double> numberList = new ArrayList<Double>();

for (int i = 0; i < sizeOfNumberList; i++) {
numberList.add(Math.random());
}

/* Write to public statics to avoid optimizing this code. */
average += average(numberList);
stdDev += standardDeviation(numberList);
}

private double average(List<Double> numbers) {
double sum = 0.0;

for (double number : numbers) {
sum += number;
}

return sum / numbers.size();
}

private double standardDeviation(List<Double> numbers) {
double mean = average(numbers);
double sumOfSquares = 0.0;

for (double number : numbers) {
sumOfSquares += Math.pow(number - mean, 2);
}

return Math.sqrt(sumOfSquares / (numbers.size() - 1));
}

private void throwThrowable(Class<? extends Throwable> throwable) {
try {
throw throwable.getDeclaredConstructor().newInstance();
} catch (Throwable t) {}

try {
throw throwable.getDeclaredConstructor().newInstance("random string: " + Math.random());
} catch (Throwable t) {}
}

private void throwThrowables() {
throwThrowable(Throwable.class);
throwThrowable(ClassFormatError.class);
throwThrowable(StackOverflowError.class);
throwThrowable(Exception.class);
throwThrowable(ClassCastException.class);
throwThrowable(NumberFormatException.class);
}
}

0 comments on commit 91d6140

Please sign in to comment.