Hacker News new | ask | show | jobs
by Matthias247 4040 days ago
Just wanted to comment on the "Blocking vs. Non-Blocking" nature of the different actor implementions. The article here says

A reason for choosing the asynchronous, callback-based approach has been that blocking plain OS threads entails significant overhead (as does the mere existence of many threads), which can be avoided with a non-blocking API. However, because Quasar – just like Erlang and Go – has true lightweight threads, blocking carries virtually no overhead

In my opinion the difference is much then whether an OS thread is blocked or not. Being able to make synchronous-looking (but not-thread-blocking) calls inside Actors still will block the Actor for other incoming messages for that amount of time. So you have states were the Actor is unresponsive - and with the right amount of dependencies between Actors you can deadlock.

A Actor which doesn't use any blocking calls internally will be more responsive and less prone to deadlock. But of course - you have to model more states explicetly. E.g. if I have an Actor routine that's like

  while true {
    var msg = await mailbox.Get();
    if (msg is XYZ) {
      var result = await doSthAsync()
      updateState(result)
    }
  }
and would like to transform that into a completly nonblocking implementation then I would need to model an extra state and probably handle messages differently in the timeframe between doSthAsync() was sent and the result is received.

This can be a good thing (you can be more responsive and all states are explicit) and also a bad thing (more verbose code).

Important is also that with the blocked Actor one get some kind of backpressure strategy for free. Whereas with the nonblocked Actor one has to handle that also explicitly.

I tried both concepts in my recent work, the blocked actor mainly with F#'s mailbox processor and the nonblocked with my own implementation and personally favor the second version now. I find it quite useful to think about and model Actors as state machines and beeing able to handle all kinds of state transitions explicitly. It also made deadlock prevention easier.

Nevertheless I'm seriously impressed about the capabilities of Quasar and Pulsar.

1 comments

I'll only add that Quasar offers several types of "send" and "receive" operations: blocking indefintely, with timeout and even "try" variants that will not block at all, as well as several mailbox types, so the developer can regulate queues, responsivity (and backpressure) as desired.