Live data from Hacker News

Actor system for the JVM developed by Electronic Arts

orbit.cloud

91–95 of 95 posts

Re: Actor system for the JVM developed by Electronic Arts

#91

So, I'm the original lead developer of this project. This was meant to be a followup to the original version of Orbit which now lives on as orbit-legacy on GitHub. Unfortunately other priorities have meant this project hasn't proceeded in the past couple of years. I wouldn't really recommend anyone use either of them. However, the ideas and implementation both for Orbit Legacy and the early version of Orbit 2 contain…

Do you have an opinion about Project Loom?

I think the JVM and particularly Java are in desperate need of improvements to the concurrency model.

When I compare the concurrency model on the JVM (and especially Java itself) to the modern competition from the likes of GoLang and C# there are clear and obvious drawbacks. Even comparing just the Java language and some other JVM languages like Kotlin and Scala, it comes up well short.

Project Loom certainly looks to be a step in the right direction. I haven't looked at it in depth recently but Virtual Threads and Continuations will be a welcome addition and last time I did look it was promising in terms of implementation.

If I were creating a new project today I'd likely reach for GoLang or DotNet (now that Core and Framework are unified) before the JVM, and if I did decide on the JVM I'd choose Kotlin over Java.

I'm historically a huge fan of the JVM and Java, and I'd like to see it back on top, but right now I think the competition is better positioned and until the many initiatives going on (such as Loom) start to have a major impact on the ecosystem, it's no longer automatically my first choice.

Re: Actor system for the JVM developed by Electronic Arts

#92
post #87

I'd like to mention the native actor model implementation CAF, the C++ Actor Framework, and share some experiences. (Disclaimer: I've been developing on CAF in the past and have a good relationship with the creator.) CAF (1) provides native actors without an VM layer, (2) type-safe interfaces so that the compiler yells at you when a receiver cannot handle a message, and (3) transparent copy-on-write messaging so that…

I still don't get why you need actors. In all my years I've never come across some problem and thought "this would be a great use for actors". Is the kind of applications that I write simply not suited to it? Many other people here in the comments have mentioned how actors can be used to serialize access to mutable state. My applications almost never have mutable state, especially not non-local mutable state that would require locks, except maybe caches. All mutable data is generally in some kind of highly available database and too large to hold in memory anyway. Message queues (like in an actor's message box) can never be in memory or they would lose data when the application crashes.

The reasoning in the book that you linked does not make sense to me. Any serious language nowadays has some kind of lightweight thread abstraction which you can spawn thousands or millions of without making a dent into system resources, so this is a non-issue. It goes on to say that

> This alleviates the need for the programmer to reason about an entire system. Instead the programmer has a fixed set of concerns, meaning they can ensure behavioral correctness in isolation, rather than having to worry about an interaction they hadn’t anticipated occurring.

which is just blatantly false. You can reason about a single actor, yes, but doing so is not helpful when you are interested in the correctness of the entire system. Since actor boundaries are an operational concern, they do not align with the domain logic. To understand the domain logic you always have to look at interactions of multiple actors (a single actor would be pointless) all with their own mutable state, all which can receive messages from anywhere at any time with no guarantees of timely reply to its own messages. A functional programming approach on the other hand is much easier to reason about with a well defined denotational semantics, no peer-to-peer interactions, no mutable state (generally) and composition of components that are aligned with domain boundaries and thus meaningful in isolation.

> Without a lightweight process abstraction, users are often forced to write parts of concurrent applications in an event-driven style which obscures control flow, and increases the burden on the programmer.

This is exactly the argument _against_ actors in my mind. Because actors communicate only through messages, they enjoy high decoupling but the price for this is horrible cohesion. Any domain logic that is spread across multiple actors will quickly become incomprehensible and unmaintainable. The same is true for event-driven microservices and a great deal of architectural work goes into making the microservices as large as possible to improve cohesion while making them as small as necessary to be independently scalable.

Re: Actor system for the JVM developed by Electronic Arts

#93
post #29

Earlier quoted context omitted.

Agreed, although it’s not always fire-and-forget (i.e. send a message and don’t wait for a response). Actors generally do support request/response style messaging, but it’s always async - it’s really only synchronous request/response communication that’s not allowed.

Not always. Goblins[0] is an example of an actor system that supports both synchronous and asynchronous communication between actors, with synchronous communication only possible if both actors are in the same “vat” (a kind of event loop). [0] https://docs.racket-lang.org/goblins/

Hi! Yeah I'm the author of Goblins :)

Yes, Goblins' "vat" model descends from E, which supports the "hybrid worldview". http://www.erights.org/

I have a tendency to call Goblins objects "actors", though some people in the community like to point out that "distributed object" is preferable since synchronous call/return is not supported in actors. But yeah.

Re: Actor system for the JVM developed by Electronic Arts

#94
post #79

Earlier quoted context omitted.

I’m curious about the following: Suppose you have an actor that is tasked to perform a long-running operation (enacted by a specific message sent to the actor). Now suppose you want to know how far the actor has already progressed with the operation, or possibly you want to pause or stop/abort the operation – basically a monitoring and controlling interface. Would that be out of scope for the actor model? Polling the…

Many actor frameworks (including Orbit, though I advise you don't use it for the reasons in my above messages) are strictly single threaded in that only one thread can operate on an actor at any one time, and by default they are also not concurrent in that only one message gets processed at once. However, while the single-threadedness is a hard requirement and behavior of the system, the rule that only one message is…

Doesn't reentrancy defeat the serial processing property that makes locks unnecessary? If a new message is accepted before the previous one has finished processing, then it can change the mutable state inside the actor. Essentially, you can never know what the state will be because at any blocking point some other message can make arbitrary changes. At that point the actor is just a crappy class with message passing instead of method calls and all the annoyances that entails.

Re: Actor system for the JVM developed by Electronic Arts

#95

Earlier quoted context omitted.

I'm curious what you see as so different in an actor vs a queue with workers. An actor's mailbox effectively acts as a queue. Is it the supporting structure surrounding an actor focused library/language? Lots of person-hours have gone into making them to work well. Some home grown queue + pool of threads working off that queue... not so much.

So pulling from the alluded to real life example, we wrote a job scheduling system. Now, each job could be defined by a lifecycle. It wasn't just a single fire and forget command, but multiple in time (a prep start, start, stop, clear, commands), and also tracking status of an external resource (looking for error states or ambiguities, etc), and could also be modified (change of start and stop times, including "now"…

So let's say I implement some job scheduling system like you suggested: One job actor instance per job and one scheduler actor instance to create new job actor instances. The job can be in one of many lifecycle states like started, in progress, etc. Unfortunately, since this is a distributed system with faults there can be network partitions, crashes and such at any moment, so every time the job actor changes state it has to write it down in some highly available database so it can be restarted if it crashes and every time it wants to do anything it has to check that database to see if someone else is already doing it. At that point the actors are basically stateless, so what's the benefit of using actors in contrast to Futures or similar stream-processing frameworks, whose abstraction boundaries are not coupled directly to operational concurrancy concerns and thus much more maintainable when you have more complicated workflows with fan-out/fan-in stages? (Not to mention that Akka Streams provides this API on top of actors with the ability to distribute work across nodes in a network without users having to know anything about the actor model).
Post reply on HN