From c85d8d6a6e877aba54d7d44fbf0bc0f49881a09d Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Tue, 18 Jul 2023 09:15:13 +0200 Subject: [PATCH] Lift the limitation regarding @Transactional and @RunOnVirtualThread. Because Narayana was pinning the carrier thread, the @RunOnVirtualThread was ignored, switching back to blocking. --- docs/src/main/asciidoc/virtual-threads.adoc | 37 ++++--------------- .../common/processor/EndpointIndexer.java | 12 +----- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/docs/src/main/asciidoc/virtual-threads.adoc b/docs/src/main/asciidoc/virtual-threads.adoc index abd75832d04d2..7b43585d445ae 100644 --- a/docs/src/main/asciidoc/virtual-threads.adoc +++ b/docs/src/main/asciidoc/virtual-threads.adoc @@ -369,6 +369,9 @@ This `synchronized` block is the culprit. Replacing it with a lock is a good solution, but it won't be enough: `synchronized` blocks are also used in `executeWithFlags(int flag)`. A systematic review of the postgresql-jdbc driver is necessary to make sure that it is compliant with virtual threads. +NOTE: Recent versions of the Postgresql driver and MariaDB driver remove the pinning. +However, pinning may still happen because of the rest of the stack. + === Reactive drivers at the rescue The vertx-sql-client is a reactive client, hence it is not supposed to block while waiting for the completion of a transaction with the database. @@ -437,30 +440,6 @@ of thousands of threads. You can refer to link:https://mail.openjdk.org/pipermail/loom-dev/2022-July/004844.html[this mail] to get more information on how we envision our future with virtual threads. -=== Our solution to the Netty problem -In order to avoid this wasting of resource without modifying Netty upstream, we wrote an extension that modifies the -bytecode of the class responsible for creating the thread locals at build time. -Using this extension, performance of virtual threads in Quarkus for the Json Serialization test of the Techempower suite -increased by nearly 80%, making it almost as good as reactive endpoints. - -To use it, it needs to be added as a dependency: - -[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] -.pom.xml ----- - - io.quarkus - quarkus-netty-loom-adaptor - ----- - -Furthermore, some operations undertaken by this extension need special access, it is necessary to - -- compile the application with the flag `-Dnet.bytebuddy.experimental` -- open the `java.base.lang` module at runtime with the flag `--add-opens java.base/java.lang=ALL-UNNAMED` - -This extension is only intended to improve performance, it is perfectly fine not to use it. - === Concerning dev mode If you want to use quarkus with the dev mode, it won't be possible to manually specify the flags we mentioned along this guide. Instead, you want to specify them all in the configuration of the `quarkus-maven-plugin` as presented below. @@ -481,11 +460,10 @@ Instead, you want to specify them all in the configuration of the `quarkus-maven - 19 - 19 + 20 + 20 --enable-preview - -Dnet.bytebuddy.experimental --enable-preview --add-opens java.base/java.lang=ALL-UNNAMED @@ -502,11 +480,10 @@ The configuration of the quarkus-maven-plugin will be simpler: .pom.xml ---- - 19 - 19 + 20 + 20 --enable-preview - -Dnet.bytebuddy.experimental --enable-preview diff --git a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java index 56a3bf6639784..5f6ce3d8a8b91 100644 --- a/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java +++ b/independent-projects/resteasy-reactive/common/processor/src/main/java/org/jboss/resteasy/reactive/common/processor/EndpointIndexer.java @@ -822,13 +822,6 @@ private boolean isRunOnVirtualThread(MethodInfo info, BlockingDefault defaultVal Map.Entry runOnVirtualThreadAnnotation = getInheritableAnnotation(info, RUN_ON_VIRTUAL_THREAD); - //should the Transactional annotation override the annotation @RunOnVirtualThread ? - //here it does : it is impossible for a transaction to run on a virtual thread - Map.Entry transactional = getInheritableAnnotation(info, TRANSACTIONAL); //we treat this the same as blocking, as JTA is blocking, but it is lower priority - if (transactional != null) { - return false; - } - if (runOnVirtualThreadAnnotation != null) { if (!JDK_SUPPORTS_VIRTUAL_THREADS) { throw new DeploymentException("Method '" + info.name() + "' of class '" + info.declaringClass().name() @@ -894,15 +887,14 @@ private boolean isBlocking(MethodInfo info, BlockingDefault defaultValue) { return false; } Map.Entry transactional = getInheritableAnnotation(info, TRANSACTIONAL); //we treat this the same as blocking, as JTA is blocking, but it is lower priority - if (transactional != null) { - return true; - } if (defaultValue == BlockingDefault.BLOCKING) { return true; } else if (defaultValue == BlockingDefault.RUN_ON_VIRTUAL_THREAD) { return false; } else if (defaultValue == BlockingDefault.NON_BLOCKING) { return false; + } else if (transactional != null) { + return true; } return doesMethodHaveBlockingSignature(info); }