8 ms·
Loom: Project Loom Early-Access Builds
- kyrra 5y agoFor those that don't know, this is fibers for Java: https://wiki.openjdk.java.net/display/loom/Main https://wiki.openjdk.java.net/display/loom/Main As someone that codes Java (using various async libraries) and has dabbled in Go, I really look forward to this, it can't come soon enough.
- emmelaich 5y agoand >... delimited continuations (of some form), and related features, such as explicit tail-call. from https://openjdk.java.net/projects/loom/ https://openjdk.java.net/projects/loom/
- omazurov 5y ago>... delimited continuations (of some form) I expect internal implementation of continuations in Loom to have non-negligible overhead which may be justified for heavy blocking I/O operations but not for CPU-bound workloads. One benchmark I'd like to see (I may want to create it myself at some point) would run a large number of light threads (fibers) which would exchange data via blocking queues (to mimic goroutines with channels). No I/O, a totally CPU-bound workload with a lot of concurrency and a good potential for scalability. Somehow, I'm not very optimistic about Loom's performance in that context (please tell me if and where I'm wrong).
- Skinney 5y agoFor a CPU bound workload you’ll be better off using one «full» thread per cpu in a pool and submitting tasks to said pool. Then again, the same would be true in Go. Loom simply brings goroutines to the JVM. Go might perform better, but that can be due to many other things not specific to the concurrency implementation (like better memory utilization because not every struct is stored on the heap in Go)
- omazurov 5y agoI thought the promise was we'd use Threads for everything and forget to worry about blocking calls. I can't run one OS thread per CPU in my proposed benchmark: I want to run millions of threads. Reimplementing it in a different concurrency model would mean Loom is hopeless for such workloads. Go may perform better but I don't think it would perform well (I see, I now have to implement my benchmark in go as well). I just don't believe their scheduler is so good.
- Skinney 5y ago> I thought the promise was we'd use Threads for everything and forget to worry about blocking calls. That is the promise, yes, but you specifically mentioned a CPU-bound task. A CPU-bound workload cannot hope to do much better than doing a concurrent task spread equally among the available CPU's, spawning more threads will just add coordination overhead. If you're spawning one million threads, each of which will perform a blocking operation, then you're likely not CPU bound (unless you're doing a System.sleep(1) or the equivalent). > I just don't believe their scheduler is so good. I believe you pick your own scheduler. By default it uses ForkJoin, which is supposed to be pretty good, uses the same conceptual implementation as Go (work stealing), but you're free to use something else.
- omazurov 5y ago> If you're spawning one million threads, each of which will perform a blocking operation, then you're likely not CPU bound Imagine a DAG with million nodes. Each node takes data from all its input edges, processes it and sends to all its output edges. Now that I have light threads I want to use them to implement all nodes. Edges are naturally implemented as blocking queues. If I feed enough data into this structure I get a CPU-bound workload with a lot of concurrency (and scalability). Yet the nodes will have to block on their input queues because data will not be ready in most cases. Now, to complicate the design, I want to have I/O tasks that read data from a file/network and feed it into the DAG and send its resulting output to the UI thread. Should I use different "threads" for different parts of the design? I'd hate to, especially given the fact that all those parts are dynamic in nature. So, of course, I'm not currently spawning a million threads to execute all those tasks but Loom says I could do that for all my tasks and my concern is that to get decent performance I'd have to explicitly separate my "CPU-bound" tasks from my "I/O-bound" tasks and use different kinds of threads for each (which I'm kind of doing right now but again the promise was...).
- lmm 5y agoWhat's the use case for that kind of behaviour? AIUI the main point of Loom is so that we can go back to writing in (logical) thread-per-request style for IO-bound network servers. If you've got a CPU-bound workload then it's presumably not interactive so writing it in high-throughput high-latency batch style would be more natural, so it's hard to think why you'd want millions of threads for a CPU-bound workload. (I guess maybe some kind of entity simulation thing where you want to write one thread per entity? But I'm not sure you'd expect a huge speedup from that versus just doing the whole thing single-threaded).
- omazurov 5y agoPlease see my example below.
- pron 5y ago1. CPU-bound problems that are not externally driven by I/O events fall under the purview of parallelism (shortening the latency of performing a single task by splitting it into cooperating tasks that employ multiple processing units) rather than concurrency (increasing the throughput of handling multiple competing, largely independent events, using scheduling). In Java, parallel streams and the low-level ForkJoinTask were made to address parallelism, whereas Loom's virtual threads are designed to tackle concurrency. It is true that some parallel use-cases are more conveniently expressed with continuations, but more on that below. 2. For CPU-bound workloads, virtually any overhead that isn't zero can come to dominate in many situations. The overhead can be made to be zero when the tasks are known in advance and can be inlined. This happens in two situations: generators, where there is one producer that can be inlined together with the consumer, and parallel workloads where all the tasks are the same. I am not aware of any single implementation, or even a single user-facing construct, that gives you the optimal experience both in those situations and in I/O-driven concurrency. If you have only one continuation construct, you must choose whether you want to favour one or the other. C++ favours the former, while Java, like Go, the latter, partly because Java already has a decent parallelism construct, and partly because we believe that the concurrent use-case delivers more value to more people. If parallel use-cases that benefit from continuations and/or generators come in high demand, we can address them later.
- drunkenmagician 5y agoAm I the only one that thinks it's odd that the Java JDK project and EA landing pages don't have a proper or even basic (in the case of loom and metropolis) summary of what the project is all about? Seems very poorly documented / managed, like its published because its supposed to be an open project, but the project team is not all that interested in your feedback...
- barbarbar 5y agoThere is this page on OpenJDK https://openjdk.java.net/projects/loom https://openjdk.java.net/projects/loom and there is a link to the wiki on that.
- capableweb 5y agoIs this the wiki page you mean? https://wiki.openjdk.java.net/display/loom/Main https://wiki.openjdk.java.net/display/loom/Main Seems to also be lacking of content. Tiny link on the right called "State of Loom" seems to have the most background information though, and should be helpful to people like me who had no idea what Loom is/supposed to be: http://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part1.html http://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part1.h...
- carimura 5y agoand https://inside.java/tag/loom https://inside.java/tag/loom for lots of content from the Loom team.
- nextaccountic 5y agoIs this proprietary software? It says it's GPLv2 with classpath exception (which forbids further restrictions) but also says > International use restrictions > Due to limited intellectual property protection and enforcement in certain countries, the source code may only be distributed to an authorized list of countries. You will not be able to access the source code if you are downloading from a country that is not on this list. We are continuously reviewing this list for addition of other countries. Maybe it's just that Oracle that doesn't want to convey the software to certain nationals, but anyone else with a valid GPL license may convey it?
- deleted 5y ago[deleted]
- zinekeller 5y agoNope, they don't violate it: https://www.gnu.org/licenses/gpl-faq.html#ExportWarranties https://www.gnu.org/licenses/gpl-faq.html#ExportWarranties Besides, they either own the code, licensed said code by a contributor or another software maker to Oracle on a perpetual, sublicensable terms or used Expat-licensed (MIT-licensed) code. All of these does not restrict Oracle from assigning any copyright conditions apart from the required attributions on Expat-licensed code. It could be closed-source and they will still be fine.
- nextaccountic 5y agoOk, it makes sense, thanks!
- Sophistifunk 5y agoYou can't sell software to North Korea no matter what license you put on it.
- chrisseaton 5y ago> which forbids further restrictions You can’t forbid yourself from applying whatever terms you want on your own code.
- shaunxcode 5y agoThis is super exciting! Really opens some new doors for languages built on top of the jvm.
- pjmlp 5y agoAnd new problems to solve, for those that went their way and now need to reconcile their vision of doing asynchronous computation with Loom.
- vemv 5y agoGenuine question - is there a concrete and practical problem that can't be solved without Loom green threads on the JVM? Generally I think that programs can be structured nicely and have them perform optimally by using traditional threads, backed by idiomatic usage of the java.util.concurrent package and integration of those vanilla threads with the NIO package. IOW, using NIO doesn't inevitably imply using an async framework (be it bespoke, or official like Loom)? Personally I've always had my reservations around async, it seems a paradigm that makes things gratuitously harder.
- clhodapp 5y agoOn the JVM, native threads are really expensive, especially in terms of memory. Loom comes from the same place of skepticism of async that you are expressing. Its goal is to make the imperative, blocking style as efficient as the async style while retaining familiar debugging tooling. Personally, I'm more skeptical of imperative, blocking programming but Loom does seem like it can only be a good thing to have access to on the JVM platform.
- vemv 5y ago> On the JVM, native threads are really expensive, especially in terms of memory. I don't think this is true if you create have approximately 1 thread for each CPU core (which is the ideal scenario in a non-async app - why would you create more threads than CPUs?). A JVM thread is basically an OS thread. So on a 64-core server you'd have 64 threads, give or take. While a server can handle a few thousands threads quite seamlessly.
- btbuilder 5y agoIf you are not using async IO and have a thread per core, if (as is quite common) your program needs to make IO calls (network being likely worst case) then the thread will sleep on a blocking IO call and CPU will be idle even if there’s work in a queue.
- 5y ago
- xanth 5y agoC# dev here so please forgive my ignorance. Is it fair to say that Loom intends to build a more efficient and transparent async/await system for the JVM?
- Skinney 5y agoI guess it would be fair to say that Loom brings the benefits of async/await without any change in language syntax, and by being compatible with your run-of-the-mill threads
- jayd16 5y agoYou're going to have a lot of replies that simply say yes but they're different tools and they have different use cases. The implicit threading of Loom works well for things like transparently dealing with IO without blocking an OS thread. For things like posting back to a UI thread, you'll still need explicit handling not unlike async/await. It seems like Java is taking a scoped approach. https://wiki.openjdk.java.net/display/loom/Structured+Concurrency https://wiki.openjdk.java.net/display/loom/Structured+Concur...
- marwis 5y agoIt says that you can implement your own scheduler for virtual threads so presumably you can make one that schedules back to UI loop.
- pjmlp 5y agoLoom avoids the coloured issue where we have to do Task.Run(() => ....) to avoid polluting the whole call stack with async Task<T>.
- the_duke 5y agoLoom and Valhalla both seem to be very powerful new features for the JVM that seem to take forever to land. Valhalla was first announced in 2014, and Loom in 2017. Does anyone have some insight on when either of these might finally be ready? For those not familiar: Valhalla: introduces "inline types" (structs) and allows using primitive types as generics. Has the potential for quite significant performance improvements because it can reduces all the pointer chasing currently required. Loom: allows Java to work like Go: code that looks single-threaded but where IO is actually driven by a runtime on a hand full of threads. As in: async without the development and debugging complexity.
- pjmlp 5y agoLook like this, it took 10 years to get modules into C++, which only VC++ from about 10 compilers, properly supports, only a subset of concepts managed to get in after 10 years, co-rountines are only at language level, everything executors and networking might only land on C++26. So I am not concerned that engineering efforts that allow .jar files from 2000 to keep running in Valhalla/Loom aware JVMs (minus modules issues) to also take equally amount of time.
- ta988 5y agoYes it seems that anything that takes more than the average tenure in a tech company is defined as "forever" now.
- debug-desperado 5y agoI'd wager they will both be ready before Go gets generics.
- pharmakom 5y agoAnyone know why they went with this rather than do-notation so that we can implement our own async etc?
- Skinney 5y agoDo notation would only benefit Java, not all the other languages on the JVM. Do-notation would also not solve the problem outlined in the "What color is my function" article. By doing it this way, the entire JVM ecosystem get's the benefits of async/await without changing the Java language. It's also easier for developers to learn (do what you're used to with threads, just use this .virtualThreadPool function instead and be extravagant with the number of threads in the pool).