[HN Gopher] Actor system for the JVM developed by Electronic Arts
___________________________________________________________________
Actor system for the JVM developed by Electronic Arts
Author : dmux
Score : 179 points
Date : 2022-04-28 14:21 UTC (8 hours ago)
(HTM) web link (www.orbit.cloud)
(TXT) w3m dump (www.orbit.cloud)
| JoeHegarty wrote:
| 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 some ideas and concepts that
| may be useful to folks.
|
| I still think there is immense value in virtual actors (Orleans
| from Microsoft is one great alternative for .NET, and Dapr also
| looks interesting) but I can't say if we'll ever get back to it.
| foob20220428 wrote:
| _> "It is heavily inspired by the Microsoft Orleans project."_
|
| It's always better to focus on delivering the game rather than
| trying to make an own engine...
| JoeHegarty wrote:
| While in general I agree with that philosophy, it doesn't
| really apply in this case.
|
| When Orbit 1 was initially developed, Orleans was not open
| source, so the initial implementation was based off the
| Microsoft Research Whitepaper.
|
| In our specific case, we had a lot of existing experience and
| services built on the JVM so adopting DotNet for Orleans
| (even if it had been available at the time) was not an
| option. The relative drop in priority for Orbit vs other
| projects was due to a need to dedicate more time to other
| parts of the platform.
|
| As a large dev/publisher EA has a sizeable central technology
| group that develops everything from engines (Frostbite) to
| services (EA Digital Platform).
|
| Ultimately I agree with the philosophy for smaller developers
| who are focused purely on making a game, but that's just not
| the reality at large companies and ultimately someone has to
| develop those services/engines.
| ackfoobar wrote:
| past: https://news.ycombinator.com/item?id=9300672
| tdstein wrote:
| How does this compare to Erlang / Elixir?
| sandGorgon wrote:
| a very interesting counterpoint is Vert.x -
| https://vertx.io/docs/vertx-core/java/
|
| Vert.x uses a concept called Verticles - which are like
| actors..with an external message bus. Which ends up being more
| practical if you start leveraging kafka, etc in the architecture.
| spacemanmatt wrote:
| Vert.x has grown on me fast! Verticles are the right
| combination of actors and good-old pragma.
|
| The community is healthy and helpful, too. I hope to stick with
| Vert.x for a long time even.
| voz_ wrote:
| Ah GC languages, a curse upon us.
| Pxtl wrote:
| I assume EA didn't make this just for funsies. What do they use
| it for?
| [deleted]
| baud147258 wrote:
| from the article on its release:
|
| http://blog.bioware.com/2015/03/30/launching-into-orbit/
|
| (HN thread: https://news.ycombinator.com/item?id=9300672)
|
| > The last-generation of Orbit powered some of the key
| technology behind the Dragon Age Keep and Dragon Age:
| Inquisition. Our plans for the next-generation framework are
| even more ambitious.
|
| So at least it was used for some of Bioware's games
| the_arun wrote:
| Is actor system same as event based systems or event driven
| architecture?
| chaostheory wrote:
| It's an alternative to working with threads. You pass "work" as
| messages to "actors" instead of using locks on resources.
| klysm wrote:
| Actors are a more specific model of computation. Definitely
| related to event based systems but far more specific.
| giancarlostoro wrote:
| I found out about this one a few years back from a former
| (online) friend who worked on it (although I'm not entirely
| certain in his specific involvement, I want to say he was the
| lead developer initially though), his name is Joe Hegarty[0].
| There was another implementation as well from him in TypeScript
| for Node.js called Ratatoskr[1].
|
| As far as I've always known him, he always works on networking
| projects, I believe he worked on the Fable 3 networking for coop
| and several other games. I can't even imagine what he works on at
| EA now honestly.
|
| JoeH if you're reading this by chance: Just remember you were an
| inspiration back in the day (mid to late 2000s) to a lot of
| people who became developers and learned a ton from your work
| back then, myself included. To this day I remember asking you
| questions almost every day. Thank you for your efforts and your
| patience.
|
| [0] https://www.joeh.ca/
|
| [1] https://github.com/ratatoskr/ratatoskr
| JoeHegarty wrote:
| Thank you for your kind words. I do indeed still work on
| networking stuff.
| btbuildem wrote:
| I can't help but recoil from a "hello world" that pulls in an
| entire container ship of dependencies.
|
| Especially that we already have a perfectly good, battle-
| hardened, and relatively lightweight implementation of Actor
| model with Erlang / Elixir.
| capableweb wrote:
| > I can't help but recoil from a "hello world" that pulls in an
| entire container ship of dependencies.
|
| Where do you see the list of dependencies? Seems to me to be
| the ones defined at https://github.com/orbit/orbit/blob/2339560
| 01f1206ccbfde72ef..., is that correct? Doesn't look like "an
| entire container ship" but maybe the NPM madness have ruined
| me.
|
| > Especially that we already have a perfectly good, battle-
| hardened, and relatively lightweight implementation of Actor
| model with Erlang / Elixir.
|
| Yeah, if you're already using Erland or Elixir, why don't you
| go with that instead? This seems to be for the JVM, so one
| could assume that the ones who want to use this, is already
| invested heavily in the JVM ecosystem (which as far as I know,
| EA is when it comes to backend servers).
| verst wrote:
| The OSS project I work on, Dapr (Distributed Application Runtime
| - an incubated CNCF project) implements the virtual actor pattern
| if anyone is interested.
|
| https://docs.dapr.io/developing-applications/building-blocks...
|
| https://github.com/dapr/dapr
| asabla wrote:
| Been digging my self deeper and deeper into Dapr, Orleans and
| similar for several years now.
|
| Super cool tech! so thank you for your contributions and future
| work on this.
| g051051 wrote:
| It'd be a lot more interesting if it wasn't in Kotlin.
| qlm wrote:
| Why does that matter? Kotlin has interop with other JVM
| languages.
| guipsp wrote:
| It does seem that some of the more interesting features
| require kotlin, which makes calling it an actor system for
| the jvm a bit meh, in my opinion.
| spacemanmatt wrote:
| You might be a candidate for Vert.x
| wiseowise wrote:
| Why?
| michaelcampbell wrote:
| To me it makes it that much more interesting, but reasonable
| people can disagree.
| newobj wrote:
| "Exactly one" is a hard concept to get right. How do they ensure
| that exactly one instance of an actor is alive at once, without
| sacrificing latency of actor start and/or while tolerating
| network partitions?
| ackfoobar wrote:
| https://proto.actor/docs/cluster-partitions/#multiple-activa...
|
| > This can be prevented by persisting state in a database with
| some form of CAS operations, e.g. Couchbase.
| mirekrusin wrote:
| That's still "at most one" - ie. even though state of
| database itself is "exactly one" (...can "hold the lock") -
| the fact that actor thread is remote, it means it can be
| partitioned/starve the rest of the system.
|
| "Exactly once" can be achieved with "at least once" +
| _local_, reliable state where you can resolve/ignore
| duplicates. But if that "local" state is actually "remote" -
| well, then you loose this guarantee (because you can be
| arbitrarily partitioned from that state so you're in square
| one again).
| lichtenberger wrote:
| Does anyone know how it compares to Akka?
| ackfoobar wrote:
| At a glance:
|
| Sending a message is simply a function call. Whereas in Akka
| it's the ask pattern where you have to manually reify the
| function call parameters into a case class.
|
| If you want to wait in processing a message in Akka, you either
| have to juggle the message queue with stashing or block a
| thread. In Orbit it is a `suspend` fun.
| joostdevries wrote:
| It's an interesting idea; not having to stash messages in the
| actor implementation when doing an async call. I did a little
| experiment what that could look like using Akka and kotlin
| suspend functions https://github.com/joost-de-vries/akka-
| kotlin
| slantedview wrote:
| I wonder what problems this project aimed to solve that Akka
| didn't already solve.
| gentleman11 wrote:
| > Orbit is a framework to write distributed systems using virtual
| actors on the JVM. A virtual actor is an object that interacts
| with the world using asynchronous messages.
|
| Could anybody elaborate on this? How does an actor differ from an
| object that uses promises to talk to a server?
| mjburgess wrote:
| Yip, that's basically just an actor.
|
| When people talk about actor-based languages or frameworks
| however, theyre suggesting syntax primitives which help express
| this more naturally.
|
| The simple pitch is: OO _where_ objects could be on any
| machine.
| dordoka wrote:
| It implements the actor model paradigm. Check this video
| https://www.youtube.com/watch?v=7erJ1DV_Tlo
| pdpi wrote:
| Objects, actors, and (micro-)services are basically the exact
| same concept at different scales.
| usrusr wrote:
| Thanks for making me feel old by not including agents in the
| list. Those seem even more similar to actors. At least until
| someone mentions BDI, then it's suddenly an entirely
| different universe.
| spinningslate wrote:
| To some approximation. The Actor Model formalism [0] requires
| certain properties, notably:
|
| 1. Communication solely by asynchronous message passing
|
| 2. A mailbox per actor that means the reception of messages
| and the processing of them is decoupled (i.e. an actor can
| receive new messages even when processing a previously-
| received message).
|
| The OO model in general supports that paradigm. Pretty much
| all mainstream OO languages are synchronous by default
| though. Call a method and the caller is suspended until the
| method returns. Multiple clients can call methods on the same
| object concurrently, but doing that safely requires some form
| of locking/protection to be implemented in the target object.
| Stated alternatively: threads in mainstream OO languages run
| "across" objects, whereas each actor has its own thread in
| the Actor model.
|
| There are certainly similarities - in the sense that both
| actors and objects encapsulate state, with reading/writing
| occurring through well-defined interfaces (messages and
| methods respectively). But the threading model is quite
| different - it's not just a matter of scale.
|
| [0] https://en.wikipedia.org/wiki/Actor_model
|
| EDIT: corrected grammar & formatting.
| asadawadia wrote:
| actor model has nothing to do with promises
| beardedetim wrote:
| Usually the difference is the "mailbox" an actor has, making
| the difference more about the level you're calling an actor
| more than the differences in any code you might write.
| diroussel wrote:
| It's not the same as async objects. There are differences
| between different score systems. But have a look at Elang and
| Akka for example.
|
| But I'm actor systems the actors maybe more stateful that you
| typical object and be location transparent. Communication
| between actors does require knowledge of if another actor is in
| process or remote.
|
| Also the actor supervising model is a completely different way
| of recovering from errors than in OO systems.
| ctvo wrote:
| This is a very broad question. I would start with understanding
| the concept of actors. You'll end up reading about Erlang,
| Akka, etc.
|
| Then what's a virtual actor and how does it differ? You'll
| eventually end up at the Orleans paper from MSFT research:
|
| https://www.microsoft.com/en-us/research/publication/orleans...
|
| It really has nothing to do with promises (as used
| colloquially) and is a way to design large distributed systems
| using message passing and localized state that's persisted.
| whoisthemachine wrote:
| A promise is a specific class of an actor -
| https://en.wikipedia.org/wiki/Futures_and_promises#Semantics...
| xeromal wrote:
| This is based on a popular and fundamental computer science
| paradigm. If you're not familiar with it, it's a good read.
|
| https://en.wikipedia.org/wiki/Actor_model
| birdyrooster wrote:
| Highly suggested watch the creator of the actor model explain
| to some skeptics. https://youtu.be/7erJ1DV_Tlo
| yashap wrote:
| Actors are useful for keeping code clean/understandable/correct
| when dealing with heavy concurrency AND lots of mutable state.
|
| Actors are like objects, but the only way to interact with them
| is sending them a message - you can't directly access their
| properties, call their methods, etc. Messages are bits of
| immutable data sent between actors asynchronously, but those
| messages go into the actor's mailbox, and then the actor
| processes them synchronously, one at a time. You can get
| parallelism by adding more actors of the same type (10 actors
| of the same type lets you process up to 10 messages
| concurrently). Because actors are totally synchronous
| INTERNALLY, and nobody can directly access their internal
| state, it's fine for them to have mutable internal state, with
| no locking/synchronization needed, and much easier to reason
| about than mutable state normally is in highly concurrent
| applications.
|
| With that being said, the actor model has a lot of inherent
| complexity. If you don't need it, don't use it. But if you
| really do need lots of concurrency and lots of mutable state,
| it's often a great choice.
|
| They're also good for distributed systems. Actors only
| communicate by sending messages to other actors, but it doesn't
| really matter if that message is sent in memory to an actor in
| the same process, or over the network to an actor on a
| different machine. So you can take a single actor system and
| split it across many machines pretty easily. Generally the
| actor framework you're using will handle delivering messages
| over the network, ensuring there's the right number of actors
| running across all nodes combined, etc.
| jfoutz wrote:
| I've read about actors from time to time for decades. I can't
| say I fully grok the concept.
|
| Kubelet wasn't necessarily designed as an actor. I think it's
| a concrete thing that people have interacted with that is a
| pretty good example of an actor. It has it's own control
| loop. It sits there and actively monitors the state of the
| node. It constantly reports the state. If something's wrong,
| it can try to correct it.
|
| Most services and objects just sort of sit around and wait to
| be called. Kubelet is a little different, it's got a main
| driving thread that's constantly looking for trouble, and
| acting on what it finds.
|
| The line is still pretty fuzzy for me, but maybe this helps
| someone connect some conceptual dots, to distinguish between
| a service and an actor.
| dragonwriter wrote:
| > Actors are like objects, but the only way to interact with
| them is sending a message - you can't access their
| properties, call their methods, etc.
|
| While the implementation in many popular, e.g. C++ and family
| descended from it, languages muddies the waters, basically
| methods in OO are a convenient way to define handlers for
| messages sent to objects, and in pure OO you also can't
| interact with objects except by sending messages to them. The
| difference between the basic OO model and the actor model is
| that OO message sends are synchronous request/response and
| actor model message sends are asynchronous fire-and-forget.
| zo1 wrote:
| So much this. This "actor model" thing as described by GP
| sounds like plain old OO and RPC with extra steps and also
| distributed. This may be a low-effort post on my part, but
| I'm 100% not impressed because it sounds like marketing
| fluff and an opportunity to rewrite native/built-in things
| using frameworks. Also justifying Yet Another Framework or
| tool hosted on an .IO domain (snarky I know) for promotions
| and endless blog posts.
| macintux wrote:
| Erlang is decades old, a highly successful (for a
| relatively niche language, anyway) proof that the actor
| model (or something approximating it) can be a great
| tool.
| astrange wrote:
| CSP/actors is from the 70s, like most CS. It is sort of
| the original OO, but that's because OO is a newer version
| that's both less powerful and over-complicated.
|
| It doesn't need to be distributed, and it's better not to
| include that because the approach to error handling gets
| a lot easier. If you're distributed every call can fail,
| be randomly slow, has marshaling costs, is untrusted,
| etc.
| yashap wrote:
| 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.
| ryukafalz wrote:
| 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/
| dragonwriter wrote:
| > Agreed, although it's not always fire-and-forget (i.e.
| send a message and don't wait for a response).
|
| Sure, you can do async request/response in the actor
| model, but the low-level basic mechanism all
| communication is built on is send a message to an actor
| mailbox and keep going. Everything else is built in top
| of that.
| activitypea wrote:
| Excellent description of the actor model, thank you!
| spinningslate wrote:
| > those messages go into the actor's mailbox, and then the
| actor processes them synchronously
|
| Not trying to be pedantic, but that's technically not true of
| the Actor formalism [0]. Quoting wikipedia:
|
| > an actor can designate the behavior to be used to process
| the next message, and then in fact begin processing another
| message M2 before it has finished processing M1.
|
| Available implementations (such as Erlang, Akka, Pony) do not
| support that pipelining so are single threaded per actor as
| you state though. As an aside, the behaviour you describe
| _is_ part of the CSP formalism [1] - a related but different
| approach to concurrent systems.
|
| [0]: https://en.wikipedia.org/wiki/Actor_model#Inherently_con
| curr...
|
| [1]: https://en.wikipedia.org/wiki/Communicating_sequential_p
| roce...
| throwawaymaths wrote:
| Just to be a bit pedantic (but important), Erlang is _not_
| an actor system. It 's a system designed for fault
| tolerance and definable failure domains. Concurrency fell
| out of those requirements and it just happens to vaguely
| look like an actor system if you squint hard enough. I
| don't believe theories of actor systems played into the
| design of Erlang.
|
| Perhaps some of the blame belongs on the creators of Erlang
| for kind of jumping on the "actor" (and later, "OOP")
| bandwagons as marketing? to try to make Erlang less scary.
| [deleted]
| spinningslate wrote:
| Fair point: Erlang wasn't _designed_ as an Actor system.
| But you don 't have to squint that hard to see the
| similarities. Again quoting wikipedia [0]:
|
| > An actor is a computational entity that, in response to
| a message it receives, can concurrently:
| send a finite number of messages to other actors;
| create a finite number of new actors; designate
| the behavior to be used for the next message it receives.
|
| > There is no assumed sequence to the above actions and
| they could be carried out in parallel.
|
| All above are true of Erlang except intra-actor
| concurrency. Even the last bullet on designating
| behaviour: An Erlang process (actor equivalent) can
| decide to use a different function when receiving the
| next message. It just can't pipeline handling messages.
|
| So Erlang isn't that far removed from the Actor model in
| its behaviour, even if it wasn't designed as an Actor
| system in the first place. One might say actors are an
| (approximate) emergent property of Erlang rather than an
| intentionally designed one.
|
| Slightly off-topic but the only system I've used that was
| designed & built from the outset as an actor system is
| Rosette [1]. It was a really interesting project, and
| does support pipelining, but has been dormant for more
| than a decade.
|
| [0]: https://en.wikipedia.org/wiki/Actor_model#Fundamenta
| l_concep...
|
| [1]: https://github.com/leithaus/Rosette
|
| --
|
| EDIT: clarified that Rosette is the only system I've
| _used_ that was explicitly based on the Actor model from
| the outset.
| throwawaymaths wrote:
| No but also key to the definition of the actor system is
| that those are the _only_ things they are allowed to do.
| Also, there 's strange stuff like naming processes for
| service discovery, and iirc something is wrong with the
| way that Erlang does selective receives that disqualifies
| it from being an actor system, and ultimately more modern
| Erlang things like ets tables and sharing memory with
| nifs.
|
| Point is all of these deviations from actor system were
| choices made by the Erlang team in the name of
| pragmatism. They all exist because there was a use case
| and the first teams using Erlang needed them for
| something real; that Erlang is _not_ an actor system is
| important, because it 's a highly pragmatic system -- not
| one that is based in theory.
| galaxyLogic wrote:
| > designate the behavior to be used for the next message
| it receives.
|
| I think that is the key insight of actor-systems.
|
| Actors don't have state. But they can calculate their
| replacement based on their immutable data. Thus the way
| an actor at a given address evolves is described by the
| functions that calculate the successor actors.
|
| Thus you get Pure Functional Programming implemented on
| top of a fabric of distributed evolving entities. You can
| understand the behavior and evolution of such a system as
| a composition of function-calls, where functions always
| produce the same result for the same arguments.
| bitwalker wrote:
| I mean, if it doesn't count as an implementation of an
| actor system, then I'm not sure what does, regardless of
| whether it was incidental to the design goals of Erlang
| as a language. It certainly walks and quacks like an
| actor system in my opinion, and I don't think you have to
| squint very hard at all to see it.
|
| Perhaps we have different ideas of what an "actor system"
| is though.
| macintux wrote:
| Dr. Hewitt typically chimes in on these threads to
| emphasize some of the differences between his model and
| Erlang. I don't recall his username to locate some of
| those.
| gentleman11 wrote:
| Sounds like an implementation of object oriented programming
| as it was originally envisioned
| solaxun wrote:
| Out of curiosity (not much experience with Actor systems), do
| these systems solve a different problem than having disparate
| processes communicate by sticking a distributed message queue
| between them? From my naive point of view it seems like alot
| of the scaling and fault tolerance concerns nowadays can be
| solved in any language, by having a queue be the interface
| between two services.
|
| Same question applies to Erlang, which I realize is not
| _exactly_ an actor system as per the below comment, and has a
| much more sophisticated error recovery story with
| supervisors, but the general question holds.
| lostcolony wrote:
| So I think the Erlang distinction is a little unrelated (I
| mean, it's technically accurate, but not because of the
| error recovery; that's an implementation detail. The
| original Actor formulation Carl Hewitt proposed was heavily
| influenced by Smalltalk semantics; whereas Smalltalk was
| truly OO, in that everything is an Object that passed
| messages, one issue it had was that objects did not equate
| to threads of execution. The Actor model, then, said each
| object executed independently. But in the same way that
| Smalltalk did not have primitives; even integers are always
| Objects, the Actor model stipulates there are no
| primitives; even integers are Actors). But I'll take a stab
| at answering what I think you're asking.
|
| If your services don't deal with internal mutable state,
| nor high degrees of concurrency then there isn't much gain
| to be had with an actor system. That said, that begs the
| question of what the queue is for; just create more
| instances, since there's no internal state to share.
|
| As soon as you start having internal mutable state and high
| levels of concurrency, that's where the actor model
| applies. Queues don't exist for concurrency (you don't need
| them; just create more executors), they exist for imposing
| sequence where it is needed (an obvious case; you have a DB
| connection, you want to only have one query at a time. So
| every desired query goes into a queue, and the process at
| the end that owns the DB connection pulls from it).
| Internal mutable state gets stored inside of an actor;
| updates and reads get serialized on that actor.
|
| At the highest level, I would describe the actor model as
| taking a 'successful' model for distributed computing, and
| making it the only model you use, even locally.
|
| In, let's say Java, for instance, using standard
| concurrency approaches, it matters where a process lives.
| My way of operating/communicating to another thread of
| execution (unit of concurrency) is very, very different
| than my way of operating/communicating to another machine.
| Locally I have threads and locks and need to be very
| mindful. When communicating to another machine, I send a
| message and that's it (maybe I expect a response, and
| timeout if I don't get one, but that's really just the same
| thing, the other machine sending a message).
|
| I don't actually need a queue involved for theoretical
| correctness unless I need to process messages in sequence
| (after all, I could have multiple copies of the other
| process, and send a message to each of them). Now, in the
| real world I do, simply because if my concurrency gets too
| large it can't be handled by what the units of concurrency
| already available (instances, threads, whatever), and scale
| up takes time, but that's really just a special case of why
| I need to impose a sequence on messages (handle these
| first, then handle these, rather than handle all of them
| concurrently).
|
| The actor model makes this the local model of communication
| (and so makes the impedance mismatch negligible between
| local and distributed; so much so that some languages it's
| actually irrelevant whether you're sending a message to a
| local actor, or a remote one). Scaling concurrency up
| internally just means spin up a new actor. When you need to
| serialize, you send messages to the same actor, where it
| ends up in a queue.
|
| So it's not solving a different problem, exactly, if that
| problem is "how do we write systems that can do multiple
| things at once", but the specifics, complexity, etc, tend
| to be pretty different. The problems it's solving are a bit
| more subjective than simply "can we handle this problem",
| and more "how well do our tools and mental model lend
| themselves to the problem we're trying to solve".
| lostcolony wrote:
| >> With that being said, the actor model has a lot of
| inherent complexity. If you don't need it, don't use it. But
| if you really do need lots of concurrency and lots of mutable
| state, it's often a great choice.
|
| I kind of disagree with this. I mean, it's kind of correct,
| if you literally have a sequential problem with immutable
| state you're gaining nothing from it, but you're also losing
| nothing (you...will have one actor, no messages being passed,
| so the only cost is the syntax of the language; the actor
| model isn't adding any complexity because you aren't using
| it).
|
| But, a lot of problems we've historically learned to view as
| sequential are in fact concurrent. Deeply concurrent. We've
| created entire concepts specifically to impose sequential
| processing upon innately concurrent activities.
|
| As an example, almost everywhere we use queues we could
| instead model as unrelated processes able to be run
| concurrently. You still may have a bit of queueing/scheduling
| for unbounded processes, but I know from production
| experience that that is far, far simpler to do and get right
| using actors than a traditional queue/priority queue and
| worker(s).
|
| And that's where it shines. It encourages you to start
| thinking about what in fact -should- be done concurrently, by
| making that easy rather than a chore as it is in most other
| languages, and that leads to -less- complexity.
| bcrosby95 wrote:
| 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.
| lostcolony wrote:
| 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" for both).
|
| Now, using actors, this was trivial to do. Each actor was
| basically a glorified state machine, with each command,
| status update, etc, a message coming in that updated the
| internal state, and caused it to change state, and, where
| appropriate, update anything it needed to (such as the
| internal timer for when it would stop the job). We loaded
| up everything that had to happen in the next 12 hours,
| via an actor that would wake up and load more
| periodically (with an actor registry to find and confirm
| what existed already, as well as used to route incoming
| commands from users to change jobs). There is no
| complexity in managing a global state of priority between
| the actors; that's a 'solved problem' by the time slicing
| the underlying actor engine is doing for us; it's well
| tested, well proven, and invisible to us. Our
| implementation allows us to treat each job as existing in
| isolation, and write our code as though it and it alone
| is the job that needs to be executed. There is no global
| synchronization state to manage (well, with the caveat of
| taking the infinite list of future jobs, and ensuring we
| have actual processes equating to those scheduled to
| start in the next 12 hours, but that's a comparatively
| simple problem, and a proper use of sequential ordering.
| We want to execute on _these_ jobs first), nor should
| their be based on the problem we 're trying to solve.
|
| Using a queue and traditional threading model though?
| Well, we'd need a synchronized priority queue, as items
| could have their priority changed at any time, from
| multiple sources. We'd also still need a registry. We'd
| need a pool of workers, that are mostly just
| blocking...hope we don't have > (number of workers)
| things needing to execute concurrently. Our complexity to
| manage all of this is high; the level of testing needed
| to validate that there aren't emergent bugs, also high.
| Our semi-realtime requirements are probably out the
| window (high contention on the queue, or high enough
| concurrency to exhaust the thread pool could lead to very
| measurable delays in updates). And ultimately, it all
| comes to the fact that the queue exists to pretend that
| the state of the world is sequential, and that we then
| had to then contort ourselves around to bring back to a
| state that allows for suitable concurrency. Updates to a
| job can end up killing a worker and inserting something
| back onto the queue, can remove something from the queue
| and reinsert it at a different position, etc, all while
| other workers are trying to access the queue
| simultaneously.
|
| Actors are the simpler solution.
|
| The comment about an actor's mailbox being a queue is
| missing the point (though, amusingly, demonstrating it).
| Queues are sequential. Actors are capable of doing only
| one thing at a time, and so when they are requested to do
| multiple things, they will do them sequentially. A
| mailbox filling with things that don't demand sequential
| processing is a code smell in an actor system. This is
| useful if you have limited resource access (queries on a
| DB connection, say), or need things to be done
| sequentially, and are very much akin to threads. But if
| you actually want multiple things concurrently...you
| should have multiple actors, not send them into the
| mailbox of one actor (which is very much the queue
| situation mentioned above; you imposed a sequential
| ordering on things you want done concurrently. Why?).
| That's the key difference; in most other languages, the
| queue is taking multiple things you actually want
| concurrently, and imposing a sequence to them. In the
| actor model, your queue is in fact things you DO want
| done sequentially; the things you want done concurrently
| should get federated out to multiple actors.
| ackfoobar wrote:
| You're exactly right.
|
| Some examples:
|
| - Some common patterns. E.g. actor hierachy and
| supervision, circuit breaker.
|
| - Persistence. The actor persists its state (changes) and
| can wake up from a sleep.
|
| - Clustering. The actor can live in another node, and you
| interact with it using the same API.
| ackfoobar wrote:
| Well I misread and couldn't edit now.
|
| What I meant is that you can launch a co/go-routine and
| have a channel that only it can read. That is like 70%
| the power of having an actor system.
|
| ---
|
| > an actor vs _a_ queue with worker _s_
|
| See the sibling comment.
|
| TLDR: Actors each has their own queue. The orderings in
| each queue are independent. This can help with
| parallelization if it fits the shape of the problem.
| dijit wrote:
| Orbit is also the name of the always online DRM system that
| Ubisoft made many years ago.
|
| Fun fact, the tech that was developed to power Orbit forked and
| evolved along largely divergent paths to be Uplay and the
| framework on which the Division and Division 2 online backends
| were made.
|
| You can still see paths referencing Orbit in uplay, especially on
| the downloads:
| http://static3.cdn.ubi.com/orbit/launcher_installer/UbisoftG...
|
| Largely C++ on Windows.
| [deleted]
| shartte wrote:
| It looks interesting, but seems to be dead.
|
| The repository has virtually no activity since september 2020.
| ackfoobar wrote:
| Oh well, looks like it has the same fate as protoactor-kotlin.
___________________________________________________________________
(page generated 2022-04-28 23:00 UTC)