oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.38k stars 1.64k forks source link

Virtual Thread support in Truffle/Native Image #7520

Open kxtbit opened 1 year ago

kxtbit commented 1 year ago

Feature request

Is your feature request related to a problem? Please describe. I am developing an implementation of the Lua programming language on Truffle/GraalVM as a hobby project. My implementation of coroutines depends on the Loom virtual threads/continuations. However, when I compile the language using native-image (GraalVM CE 21+35.1), attempting to create a virtual thread results in java.lang.UnsupportedOperationException: Virtual threads are not supported together with Truffle JIT compilation.

Describe the solution you'd like. It would be useful if virtual threads were supported alongside Truffle JIT compilation in native images (and preferably the underlying jdk.internal.vm.Continuation interface as well, but I could get by without it) to have an efficient and interop-friendly way of implementing coroutines, fibers, and similar constructs in some programming languages.

Describe who do you think will benefit the most. Developers of Truffle-based languages would benefit the most, especially those working on languages like Lua whose coroutines cannot be easily implemented within the framework without virtual threads/continuations.

Describe alternatives you've considered. It may be possible to use alternatives such as JavaFlow, but many of these seem to no longer be maintained, be less robust than Loom continuations, and not play well with Truffle interop.

Express whether you'd like to help contributing this feature I don't have the experience necessary to help implement this myself.

iitsoftware commented 11 months ago

I vote for this feature, too! You should implement all features and not spare out the most important one - virtual threads.

Our messaging system SwiftMQ relies on GraalVM. We force our customers to use it. We are currently in the process of moving our platform thread pools to virtual threads.

SwiftMQ includes a micro service engine called SwiftMQ Streams. With that you can inject JS (aka a Stream) into a broker. This script registers various callbacks at the engine via the Java-implemented Stream Interface during script eval. Such as listeners for messages on a queue etc. Subsequently, the callbacks are activated from the Java side and the Stream processed it accordingly.

Every Stream runs in its own Context, driven by a dedicated event loop. All event loops of all Streams are currently served from a single shared thread pool. Events from one event loop might be executed by different threads from this pool but it is ensured that only one thread accesses the Context. So every Stream is single-threaded. Because of possible different thread executions on a single event loop we may have lots of heavy-weight thread context switches. To avoid that, we plan to use a single virtual thread per event loop and let the JVM schedule them on carrier threads.

SwiftMQ Streams is also used from Flow Director which is a no-code platform, based on so-called flows where you connect flow components graphically to flows and then automatically deploy and execute them. Flows are generated to JS as SwiftMQ Stream.

SwiftMQ itself has a non-blocking design with event loops everywhere and associated thread pools for execution. We are currently refactoring everything to a virtual thread per event loop. However, the SwiftMQ Streams engine is the only part we cannot refactor because you don't support virtual threads in Truffle.

Please consider to support virtual threads in Truffle! Thanks a lot!

kassifar commented 11 months ago

Hello @kxtbit,

Thank you for your feature request, we will be taking a look at it.

wirthi commented 11 months ago

Hi @kxtbit

Note that both GraalVM (JIT) and GraalVM Native Image support Virtual Threads. We are even following the latest changes from upstream (Open)JDK on a weekly basis and implementing them for GraalVM. Any regular Java application can make full use of that on GraalVM.

As you describe, we are not supporting the combination of Truffle Languages and VirtualThreads right now. This is on the roadmap, but I can't give you any ETA on it. Maybe @chumer has some insight?

Christian

iitsoftware commented 11 months ago

Hi Christian,

all good. We are using 23.1.1 and virtual threads working fine there - except for truffle.

Would be nice if that would be supported in near future.

Andreas

iitsoftware commented 11 months ago

Btw, my impression is that you don't see many use-cases for this. But there are as soon as you invoke a polyglot language from Java. That's why I have explained my use-case in more detail.

msievers commented 11 months ago

Although it's not exactly the same error message, the following use case seems related from my perspective.

In the current Spring Boot 3.2, if you activate the newly introduced virtual threads support in Spring Boot, for example, Tomcat then uses a virtual thread executor. If you then try to create a polyglot context for the execution of code (e.g., JavaScript) along with an optimizing runtime during a Spring MVC request/response cycle, the following message appears:

Using polyglot contexts on Java virtual threads is currently not supported with an optimizing Truffle runtime. As a workaround you may add the -Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime JVM argument to switch to a non-optimizing runtime when using virtual threads. Please note that performance is severly reduced in this mode. Loom support for optimizing runtimes will be added in a future release.

The message quite clearly states that there is currently no support for virtual threads when using an optimizing runtime and that this will be provided at a later date. However, it would be highly desirable if this could be implemented in the foreseeable future, as otherwise, one would have to choose between using the optimizing runtime and the use of virtual threads.

nikolafon commented 9 months ago

Can we get any timeline for Loom support for optimising runtime, please?

chumer commented 9 months ago

Sorry, I can't provide a timeline yet. We will do what we can. HotSpot support is likely to land before support in Native Image.

cjaeriksson commented 8 months ago

This is a major deal for us as we allow creating scripts that perform many blocking operations (database & network access etc). These scripts can be triggered in many ways but it is all very similar to what @iitsoftware has described already. Would greatly appreciate support for this!

eregon commented 7 months ago

I am working on adding support for VirtualThread with Truffle on HotSpot. I am also planning to add TruffleThreadBuilder#virtual to create a polyglot virtual thread from within a Truffle language.

The build-time error mentioned in the issue description (java.lang.UnsupportedOperationException: Virtual threads are not supported together with Truffle JIT compilation.) no longer happens since GraalVM 24.0.0. Instead, Native Image automatically detect the usage of Truffle JIT compilation and if so uses the "fallback" implementation for VirtualThread, specifically BoundVirtualThread which uses one platform thread per VirtualThread.

So building a Native Image using Truffle JIT compilation + VirtualThread works now, albeit by using one platform Thread for each VirtualThread. Running the image still fails due to the Using polyglot contexts on Java virtual threads is currently not supported with an optimizing Truffle runtime check, but we are considering to make it a warning/suppressible soon. That should probably unblock most use cases mentioned above, unless one creates thousands of virtual threads calling to Truffle or relies heavily on the specific performance differences between platform threads and virtual threads.

Supporting continuations + Truffle JIT compilation on Native Image would require supporting continuations + deoptimization on Native Image, which is a large effort, so that will take longer and is not currently worked on.

edgebroker commented 7 months ago

Not sure if I understand that correctly. HotSport: 1 virtual thread = 1 platform thread? And yes, we might using thousands of virtual threads.

msievers commented 7 months ago

@eregon We use GraalVM in a Spring Boot Java application to enrich business logic with custom JavaScript snippets. For security reasons, we use polyglot sandboxing with a SandboxPolicy.UNTRUSTED.

Am I correct in assuming that the JavaScript implementation which provides the UNTRUSTED sandbox, namely js-isolate, internally deals with native-image code and therefore it is currently not possible to use polyglot sandboxing together with virtual threads without creating a platform thread for each virtual thread?

If that were the case, it would unfortunately contradict the purpose of using virtual threads for our specific use case and make them de-facto unusable, since we specifically want to prevent platform threads from being created for each request, especially against the background of scripts initiating external I/O and waiting on it.

eregon commented 7 months ago

Not sure if I understand that correctly. HotSport: 1 virtual thread = 1 platform thread? And yes, we might using thousands of virtual threads.

On HotSpot we plan to support Truffle with Continuation-based VirtualThread, i.e. full support.

msievers commented 5 months ago

@eregon Let me try to elaborate on why support for virtual threads in native-image is an important feature from my perspective.

For example, when using GraalVM to extend business logic with JavaScript like we do (with the main applications implemented in Java), we must rely on strong sandboxing for security reasons. As nicely detailed in the following source

https://www.graalvm.org/latest/reference-manual/embed-languages/#polyglot-isolates

the enhanced sandboxing—everything greater than or equal to SandboxPolicy.ISOLATED—relies on native-image isolates. This means that if I want (or need) to use such a sandbox policy for security reasons, I automatically have to use a native-image isolate engine.

Therefore, I ultimately do not have the option to switch to GraalVM's virtual threads support on Hotspot because the use of advanced sandbox capabilities essentially locks me into using the native-image isolated engine.

ujibang commented 5 months ago

Virtual thread support in native-image for Truffle is crucial for our use case. Let me elaborate on why this is so important for us.

I am the main committer of RESTHeart, an API framework that supports polyglot development, enabling the implementation of web services in both Java and JavaScript. Our latest version has transitioned to using virtual threads, which has significantly improved performance and scalability.

RESTHeart and its plugins can also be built as native images, and we provide a Docker image of RESTHeart as a native image. However, we currently avoid including the Truffle runtime in our native image due to conflicts with virtual threads. This workaround leads to suboptimal JavaScript support, hindering the polyglot capabilities that are central to RESTHeart's value proposition.

By enabling virtual thread support in native-image for Truffle, we could fully leverage both virtual threads and optimal JavaScript support. This would enhance the performance and flexibility of RESTHeart, benefiting all users who rely on its polyglot development features.

eregon commented 5 months ago

I merged https://github.com/oracle/graal/commit/61bb7361d0444557e2545fddd2c271a86cd3b16e, see the sdk CHANGELOG and the Truffle CHANGELOG. This will be part of the upcoming GraalVM for Java 23 release (= Truffle 24.1). It will also work when using Truffle 24.1 on GraalVM for JDK 21 thanks to Truffle unchained.

I'll copy the sdk changelog here for convenience:

So it is now possible to use Truffle with virtual threads on both HotSpot and Native Image, with the above limitations.

For Continuation-based Virtual Thread support on Native Image, that requires implementing deoptimization from virtual threads on Native Image, and adjust the Truffle support e.g. to avoid per-platform thread state.

Polyglot isolate are currently not supported on virtual threads as native-image support for virtual threads needs to be implemented first, and there are many additional challenges for polyglot isolates. For polyglot isolates, a solution/workaround is to only use them on non-virtual threads, which could be done via a thread pool/ExecutorService/etc in the application using it.

iitsoftware commented 5 months ago

65535 is the limit of virtual threads using polyglot languages or is it the total limit of the VM?

Is it included in the nightly builds?

chumer commented 5 months ago

65535 is the limit of virtual threads using polyglot languages or is it the total limit of the VM?

That limit applies to a single polyglot context. One polyglot context can be entered with a max of 65535 different threads (virtual or platform).

chumer commented 5 months ago

Is it included in the nightly builds?

Yes, it will be included in the next nightly build.