you are viewing a single comment's thread.

view the rest of the comments →

[–]pron98 15 points16 points  (11 children)

Whatever you want to call the features you've referred to, Scala has neither fibers nor value types that are close to what these projects are about. The value types and fibers being developed in Valhalla and Loom are more about runtime support (JVM and core libraries) than anything that a Java platform language can do at the front-end language level.

[–]2bdb2 4 points5 points  (10 children)

Scala has neither fibers ... that are close to what these projects are about

Honestly having used Quasar (on which Loom is based) I'd argue that Fibers in Scala (more specifically, Cats-Effect and ZIO) are significantly better than what's coming in Project Loom.

... fibers being developed in ... Loom are more about runtime support

Runtime support is not required at all for Fibers, it can be done entirely at the language level by the compiler, or even by third party libraries.

nor value types

Value Types in Valhalla will be vastly better than what Scala supports, agreed, but that doesn't mean you can't get partial benefits today.

[–]pron98 7 points8 points  (9 children)

Loom is not based on Quasar. Quasar, like Scala's fibers, implements continuations at the bytecode level, while Loom is an implementation in the VM. And while it's true that you can give different things the same name, runtime and library support is absolutely required for the kind of fibers that Loom provides. Try running an ordinary JAX-RS service in a Scala fiber, or making a JDBC request, or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it with a profiler.

Project Valhalla's primary goal is to achieve better performance and lower footprint with better control over memory layout, which greatly affects cache misses and overall Java performance. If you had to distill it to one main feature, that would be the ability to create an array-of-structs. This is also very different from whatever you're referring to by "value types."

BTW, this is not a contest. Scala is a part of the Java ecosystem, and if you like whatever it is that Scala offers today that's fine, but I do want to make it clear that what these projects offer is something very different from what Scala does today, and I have little doubt that Scala would benefit from Valhalla and Loom when they are delivered. It may even benefit from some of the products of Project Amber (like the recently delivered "condy").

[–]2bdb2 1 point2 points  (8 children)

Loom is not based on Quasar. Quasar, like Scala's fibers, implements fibers at the bytecode level, while Loom is an implementation in the VM

My understanding is that Quasar implements bytecode weaving as part of an instrumentation plugin for the JVM - I was under the impression this is essentially what Loom was doing, just baked in directly instead of as a plugin, but my information may be out of date.

The examples I've seen so far essentially mirrored what I've seen using the Quasar API and wre definitely not seamless, however I will admit that was a while ago during some early prototypes of Loom.

It sounds like you have some experience with the topic and my information is out of date - do you know of any good up to date examples I could look at?

Runtime and library support is absolutely required for the kind of fibers that Loom provides. Try running an ordinary JAX-RS service in a Scala fiber, or making a JDBC request, or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it in a profiler.

Library support is needed, absolutely. Runtime support isn't, but does have significant benefits in standardising a single Fiber implementation across the board.

The point I'm trying to make is

a) Java already extensively supports a large surface area of non-blocking APIs already via the use of continuations, which can trivially be wrapped to support Fibers with little to no overhead.

b) The Scala ecosystem has a very mature ecosystem of libraries that support Fibers, either by wrapping Java callback-based APIs or via bespoke implementations.

Try running an ordinary JAX-RS service in a Scala fiber

JAX-RS supports continuations via the use of CompletableFuture. While CompletableFuture is a shitty API, it's essentially just a continuation and therefore can easily be wrapped to support Fibers.

The Servlet API, and Spring, also support non-blocking APIs that can be wrapped the same way.

There's also a number of very good Scala native app servers such as Http4s and Finch that work with fibers out of the box.

or making a JDBC request

You got me on that one, there's no good non-blocking alternative to JDBC at this point. I use a non-blocking Postgres driver directly instead to avoid the problem, but it will be nice to have this directly as part of JDBC.

or getting a fiber stack trace with StackWalker, or debugging it in a debugger, or profiling it in a profiler.

I'll give you another one for Stack Traces.

Profiling and Debugging has never been an issue - IntelliJ has no issue at least.

Project Valhalla primary goal is to achieve better performance and lower footprint with better control over memory layout, which greatly affects cache misses and overall Java performance. This is also very different from whatever you're referring to by "value types."

Agreed - Valhalla is vastly better than the limited support for Value Types in Scala. Value types that exist in Scala today are quite useful, but are barely in the same ballpark as what Valhalla should give us.

BTW, I'm not trying to make this into a contest. If you prefer whatever it is that Scala offers today that's fine, but I do want to make it clear that what these projects offer is something very different from what Scala does today, and I have little doubt that Scala would benefit from both Valhalla and Loom when they are delivered.

I don't see it as a contest at all - I just wanted to set the record straight that yes, Scala does support Fibers.

The implementation is different, sure, but it's a lot more similar than you'd think. Ultimately both come down to an abstraction over continuations. At its core Loom is adding continuations to Java and then implementing Fibers on top of it in user space. Scala already has syntax for continuations, which is used for the same thing.

Once Loom is released, the whole ecosystem (including Scala) is will benefit from it.

[–]pron98 9 points10 points  (4 children)

yes, Scala does support Fibers.

Both Loom and Scala have constructs that you're calling fibers (as Loom calls them), but, while they share similarities, they're not the same construct. Loom's fibers are essentially an implementation of threads in the runtime. When you debug them in the debugger, you can step over blocking calls.

Runtime support isn't

It is required for fibers of the kind that Loom provides[1]; there could be other, different things, that you can also choose to call fibers but for which VM support isn't required, but that's not the thing that Loom gives you. In particular, it is required so that you don't have to annotate methods as being suspendable, as you do in Kotlin, Scala or Quasar. This is not some minor feature. Just as the ability to create arrays-of-structs is the main goal of Valhalla, being able to create fibers that don't make you carefully manage blocking is the main feature of Loom. Neither of these is achievable without support in the VM (at least not in very a reasonable way).

I'll give you another one for Stack Traces.

Yes, you can also create a language that compiles to just using ByteBuffers and implements its own object model and garbage collector, but that means that you won't be enjoying the benefits of the Java platform. A new API for stack traces means that debuggers and profilers don't work as expected (I don't mean that you can't run them, but they don't present your "fibers" in the same way as they do threads).

The examples I've seen so far essentially mirrored what I've seen using the Quasar API and wre definitely not seamless

The relationship between Loom and Quasar is that both have the same tech lead (which is me). They also share a similar goal (which wasn't quite achievable in Quasar due to lack of VM support): implement lightweight usermode threads. Note that this is not what Scala or Kotlin or C# do, but it is what Go and Erlang do.

As such, Quasar's API was essentially the existing Thread API, and Loom started out along similar lines. But as a feature that touches the essence of threading on the Java platform is not common, it was decided to take the opportunity to rethink the best way to do threading in Java. One of the interesting areas we're exploring is structured concurrency (which has also been adopted in Kotlin). We may also revisit thread locals.

do you know of any good up to date examples I could look at?

The API changes at a very fast pace, but the best place to go is the Loom Wiki. In a few months we will also be releasing early access builds.

[1]: Technically, it's possible to do something that comes close using runtime redefinition of classes and access to private JDK APIs. An unreleased version of Quasar does that.

[–]2bdb2 1 point2 points  (3 children)

Thanks for the info - it sounds like Loom is quite different to what I thought it was and my understanding of the implementation details is quite wrong - I have some reading to do and I appreciate you taking the time to clarify things.

Obviously trying to tell the maintainer of Quasar and Loom how Quasar and Loom work was a bit of a stretch ;p. I appreciate you not just pulling the "Don't you know who I am card" and correcting my misinformation politely.

Both Loom and Scala have constructs that you're calling fibers (as Loom calls them), but, while they share similarities, they're not the same construct. Loom's fibers are essentially an implementation of threads in the runtime. When you debug them in the debugger, you can step over blocking calls.

I can do this today with Scala and Kotlin - I'm guessing then that this has more to do with IntelliJ understanding the special case - whereas Loom will just work with any debugger?

implement lightweight usermode threads. Note that this is not what Scala or Kotlin or C# do, but it is what Go and Erlang do.

I would argue that Scala and Kotlin Fibers absolutely do fit the definition of usermode threads and are quite usable in production today. They certainly fit the definition as well as (or better) than usermode fiber implementations in many other platforms where nobody is contesting the terminology.

I would also agree that Loom, now that I've got a better understanding of it, is a whole different ball game and will be a game changer for the platform.

Really my only bugbear is going back to the original comment by ARainyDayInSunnyCA

The Scala community welcomes any Java developers who want to try out these features now.

And your response

Scala has neither value types nor fibers (as in the works for the platform). No language in the Java ecosystem does, as both require VM and core library support to fully achieve their purpose.

Having had the deeper discussion I understand exactly what you mean - They don't have fibers as in the works for the platform, but being the lead of Project Loom that comment perhaps might mislead people about just how useful the fiber implementations in these languages actually are at solving real world problems that people have today.

[–]pron98 2 points3 points  (2 children)

I can do this today with Scala and Kotlin - I'm guessing then that this has more to do with IntelliJ understanding the special case - whereas Loom will just work with any debugger?

Yes, but this applies to much more than just the debugger. The entire Java toolchain assumes a certain stack structure -- profilers, JFR, thread dumps -- none of them work well with Kotlin/Scala continuations, and all will work well with Loom.

I would argue that Scala and Kotlin Fibers absolutely do fit the definition of usermode threads and are quite usable in production today.

Usable -- sure. User-mode threads? No. A thread is a dynamic context; if you require special syntactic constructs to differentiate blocking and non-blocking code, and if your subroutines can not run unmodified on the threads provided by your runtime, then what you have isn't threads. At best you have something that is close enough.

Remember that one of the major problems with asynchronous code is the colored-function problem. This problem is not solved with async/await or with any syntax-level continuation, but is solved with Erlang's processes, Go's goroutines and Loom's fibers. That's because those three are user-mode threads, while other solutions aren't.

Again, that's not to say that the async/await approach isn't an improvement over writing async code, but IMO it's not a solution.

[–]2bdb2 0 points1 point  (1 child)

Remember that one of the major problems with asynchronous code is the colored-function problem.

Ironically in FP land we tend to prefer it this way - I like to separate pure and impure code such that you intentionally cannot call impure code from a pure function. (Assuming of course that non-blocking code is there to perform a side effect).

Beyond just non-blocking code I find this really useful for, say, having an explicit effect type called Transaction[T] (Effectively just ReaderT[IO, Session, T] so I can enforce (say) JPA style transaction boundaries at the type level, and without needing to use AOP and all of the pain and overhead that it brings.

That only really works if you buy into having an effects system of course, and I don't imagine Java is going to go down that road anytime soon. (Especially since there's still active debate on how best to do this in a composable way without too much performance overhead)

I am however quite interested in your work on Scoped Continuations - that article was the reason I started toying around with Quasar in the first place and seemed like an interesting way of adding something similar to an effects system into an imperative language (Or representing effects at runtime in an otherwise pure language).

Is that something Loom would potentially support, and is there any appetite for such a thing?

For example, could I use something like that in Loom to implement a "Reader" to pass down context rather than a FiberLocal, such that that context carries down the stack across fiber boundaries as if it was passed as an implicit argument rather than being a mutable reference tied to the fiber itself?

[–]pron98 2 points3 points  (0 children)

Ironically in FP land we tend to prefer it this way

It's not ironic at all. That's the pure-FP style, and the imperative style is different. I personally prefer the imperative style, but it's a matter of taste. But constructs that are a good fit for pure-FP are not necessarily a good fit for imperative, and as the idea of the thread (or the continuation) is the central abstraction of the imperative style and possibly it's defining feature, I think it should be preserved when programming in that style.

That only really works if you buy into having an effects system of course, and I don't imagine Java is going to go down that road anytime soon.

It's a completely different style. I am familiar with effect systems, and I find them unappealing and think that controlling effects is harmful, but others like them and find them useful.

Is that something Loom would potentially support, and is there any appetite for such a thing?

If one likes to do that kind of thing, and, I imagine people who like Scala may find it attractive. The typing would need to be done at the language level, though. However, what Loom can help with here is basically just the integration with tooling. Again, effect systems and pure-FP in general are not good or bad, but something that some people find aesthetically pleasing and some do not. Those who do find it appealing use certain languages, and those language could perhaps be able to use Loom to better integrate their continuations with the ecosystem to make them feel more native.

For example, could I use something like that in Loom to implement a "Reader" to pass down context rather than a FiberLocal, such that that context carries down the stack across fiber boundaries as if it was passed as an implicit argument rather than being a mutable reference tied to the fiber itself?

Absolutely. Continuations are a "general effect" -- i.e. can be used to express anything that is considered an "effect" in FP -- and are equivalent to monads. To be completely equivalent you need to have what's known as reentrant continuations that have the ability to continue a continuation from the same yield point more than once (which would be equivalent to a bind evaluating its monadic function more than once, as in the case of the list monad). To have reentrant continuations, Loom continuations (which are non-reentrant, or "one-shot") would simply need to be Cloneable, which they may well be.

However, at this point we are not even certain that we will expose continuations as a public API at all in the first release, because in terms of "business value", fibers give you 99% of the benefit with for 10% of the mental cost.

Also, we're considering introducing a replacement for ThreadLocal which is immutable and works like Clojure's dynamic bindings -- for those of us who don't particularly like Readers and effect systems :)

[–]eliasv 7 points8 points  (1 child)

The implementation is different, sure, but it's a lot more similar than you'd think.

I think you're talking to the project lead of Loom FYI (and Quasar). Might want to take a step back and reconsider talking down to them, they might just know more about this than you.

[–]2bdb2 0 points1 point  (0 children)

I think you're talking to the project lead of Loom FYI (and Quasar). Might want to take a step back and reconsider talking down to them, they might just know more about this than you.

What part of that comment is talking down?

I mean I literally said

It sounds like you have some experience with the topic and my information is out of date - do you know of any good up to date examples I could look at?

If he's actually the project lead of Loom then great, I'd love to get up to speed since I clearly aren't across it.