-
Bug
-
Resolution: Fixed
-
P3
-
21
-
b27
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Linux x64
OpenJDK Runtime Environment (build 21-ea+23-1988)
OpenJDK 64-Bit Server VM (build 21-ea+23-1988, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Enabling class load or similar events slows down vthread creation by factor 10 compared to just enabling JVMTI, even when no classes are loaded anymore. Enabling JVMTI alone is only a factor two compared to running without JVMTI. Adding or not adding the can_support_virtual_threads capability does not matter.
Some timing with the attached sample:
$JAVA_HOME/bin/java VThreadClassLoad
duration: 1205 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad=noevent VThreadClassLoad
vthread capability added
class load event not enabled
duration: 2506 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad VThreadClassLoad
vthread capability added
class load event enabled
duration: 36212 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad=nocap VThreadClassLoad
vthread capability not added
class load event enabled
duration: 36043 ms
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
With the attached sample and JAVA_HOME set to a JDK 21:
g++ -shared -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC VThreadClassLoad.cpp -o libVThreadClassLoad.so
$JAVA_HOME/bin/javac VThreadClassLoad.java
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad VThreadClassLoad
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Timings roughly similar to just enabling JVMTI
ACTUAL -
Timings more than 10 times slower than just enabling JVMTI
---------- BEGIN SOURCE ----------
VThreadClassLoad.java ------------------------------------------
import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VThreadClassLoad {
public static void main(String[] args) {
for (int i=0; i<3; i++) {
work(); // warmup
}
long startTime = System.nanoTime();
work();
System.out.println("duration: " + Duration.ofNanos(System.nanoTime() - startTime).toMillis() + " ms");
}
private static void work() {
try (ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000_000; i++) {
executorService.execute(() -> {});
}
}
}
}
------------------------------------------------------
VThreadClassLoad.cpp -----------------------------
#include <jvmti.h>
#include <cstdlib>
#include <cstring>
#include <vector>
namespace {
jvmtiEnv *jvmti = nullptr;
void checkJvmti(int code, const char* message) {
if (code != JVMTI_ERROR_NONE) {
printf("Error %s: %d\n", message, code);
abort();
}
}
void JNICALL classLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass) {
}
}
extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
if (vm->GetEnv(reinterpret_cast<void **>(&jvmti), JVMTI_VERSION) != JNI_OK || !jvmti) {
printf("Could not initialize JVMTI\n");
abort();
}
if (options && strstr(options, "nocap")) {
printf("vthread capability not added\n");
} else {
jvmtiCapabilities capabilities;
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_support_virtual_threads = 1;
checkJvmti(jvmti->AddCapabilities(&capabilities), "adding capabilities");
printf("vthread capability added\n");
}
if (options && strstr(options, "noevent")) {
printf("class load event not enabled\n");
} else {
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.ClassLoad = &classLoad;
checkJvmti(jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)), "setting callbacks");
checkJvmti(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, nullptr), "enabling class load event");
printf("class load event enabled\n");
}
fflush(stdout);
return JVMTI_ERROR_NONE;
}
---------------------------------------
---------- END SOURCE ----------
FREQUENCY : always
Linux x64
OpenJDK Runtime Environment (build 21-ea+23-1988)
OpenJDK 64-Bit Server VM (build 21-ea+23-1988, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Enabling class load or similar events slows down vthread creation by factor 10 compared to just enabling JVMTI, even when no classes are loaded anymore. Enabling JVMTI alone is only a factor two compared to running without JVMTI. Adding or not adding the can_support_virtual_threads capability does not matter.
Some timing with the attached sample:
$JAVA_HOME/bin/java VThreadClassLoad
duration: 1205 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad=noevent VThreadClassLoad
vthread capability added
class load event not enabled
duration: 2506 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad VThreadClassLoad
vthread capability added
class load event enabled
duration: 36212 ms
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad=nocap VThreadClassLoad
vthread capability not added
class load event enabled
duration: 36043 ms
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
With the attached sample and JAVA_HOME set to a JDK 21:
g++ -shared -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC VThreadClassLoad.cpp -o libVThreadClassLoad.so
$JAVA_HOME/bin/javac VThreadClassLoad.java
LD_LIBRARY_PATH=. $JAVA_HOME/bin/java -agentlib:VThreadClassLoad VThreadClassLoad
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Timings roughly similar to just enabling JVMTI
ACTUAL -
Timings more than 10 times slower than just enabling JVMTI
---------- BEGIN SOURCE ----------
VThreadClassLoad.java ------------------------------------------
import java.time.Duration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VThreadClassLoad {
public static void main(String[] args) {
for (int i=0; i<3; i++) {
work(); // warmup
}
long startTime = System.nanoTime();
work();
System.out.println("duration: " + Duration.ofNanos(System.nanoTime() - startTime).toMillis() + " ms");
}
private static void work() {
try (ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000_000; i++) {
executorService.execute(() -> {});
}
}
}
}
------------------------------------------------------
VThreadClassLoad.cpp -----------------------------
#include <jvmti.h>
#include <cstdlib>
#include <cstring>
#include <vector>
namespace {
jvmtiEnv *jvmti = nullptr;
void checkJvmti(int code, const char* message) {
if (code != JVMTI_ERROR_NONE) {
printf("Error %s: %d\n", message, code);
abort();
}
}
void JNICALL classLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass) {
}
}
extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
if (vm->GetEnv(reinterpret_cast<void **>(&jvmti), JVMTI_VERSION) != JNI_OK || !jvmti) {
printf("Could not initialize JVMTI\n");
abort();
}
if (options && strstr(options, "nocap")) {
printf("vthread capability not added\n");
} else {
jvmtiCapabilities capabilities;
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_support_virtual_threads = 1;
checkJvmti(jvmti->AddCapabilities(&capabilities), "adding capabilities");
printf("vthread capability added\n");
}
if (options && strstr(options, "noevent")) {
printf("class load event not enabled\n");
} else {
jvmtiEventCallbacks callbacks;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.ClassLoad = &classLoad;
checkJvmti(jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks)), "setting callbacks");
checkJvmti(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, nullptr), "enabling class load event");
printf("class load event enabled\n");
}
fflush(stdout);
return JVMTI_ERROR_NONE;
}
---------------------------------------
---------- END SOURCE ----------
FREQUENCY : always
- relates to
-
JDK-8320239 add dynamic switch for JvmtiVTMSTransitionDisabler sync protocol
-
- Resolved
-
-
JDK-8321219 runtime/jni/FastGetField: assert(is_interpreted_frame()) failed: interpreted frame expected
-
- Closed
-