OTP counterpart in golang?

I have some experience using OTP, but know basically nothing about golang. My question is that is there an alternative to OTP in golang. I mean GenServer, Supervisor and Supervision Tree, if I want to use similar stuffs in golang.

A says the design idea of BEAM is ‘let it crash’, but in golang, it is ‘let us handle’. Therefore there is no counterpart.
B says they use vagrant or docker for similar tasks.
C says golang is cooperative scheduling, and also BEAM is, while there is a fixed reduction count for each process, so it is preemptive scheduling for programmers, thus there is no starvation.

Any thoughts?

There is a library called Suture that tries to mimic supervision trees in a Go way. It’s different because at a fundamental level goroutines have different constructs, but it’s worth looking at.

1 Like

I don’t think there is way around the cooperative schedule issue other than invoking the go scheduler manually. However, here are a few alternatives for other things:

  1. Process inbox => Golang channels. However, golang can have multiple processes receiving messages from the same channel and the channels need to have a buffer limit, unlike unlimited messages in erlang.
  2. Supervision: Like @brightball mentioned suture aims to provide something similar. However, I haven’t really played with it.
  3. :ets => Golang has syncmaps now.

One of the big differences is that erlang processes are addressable using a pid, whereas golang processes are not. This makes a huge difference in how you architect things.

1 Like

I don’t think you can properly implement OTP in Go, due to some lack of guarantees in the runtime layer. In particular, with go runtime:

  • an undeferred panic takes down the whole system
  • it’s not possible to forcefully terminate a busy goroutine
  • shared memory does not guarantee state isolation, so even if you defer a panic the state might be corrupted

So, while you could to some extent simulate OTP, there would be some edge cases lurking around, which AFAIK can’t be completely solved.

Take a look at my talk on this topic for more details.

8 Likes


Is this the evidence that scheduling in golang is cooperative

Yes. People say that Go is “partially preemptive”, since in many cases a goroutine can still yield. Nonetheless, there are cases where it doesn’t happen, so it’s not fully preemptive, and therefore IMO it’s not preemptive.

IIRC, the simplest example which blocks the scheduler indefinitely is for {}.

Also, you can take a look at this issue.

2 Likes

Thank you very much!

Uh, who says that go is partially pre-emptive? I’ve looked at it’s implementation in the past and at the very least it is ‘entirely’ cooperative (per thread) when I saw… o.O

It has some preemption since 1.2. Take a look here.

1 Like

That is not preemption, that is still cooporative scheduling, they just inject a ‘should I schedule’ call in some loops and such. :wink:

Preemption is well defined as a running thread being frozen/moved/paused/etc by an outside observer. :slight_smile:

Potato, potahto :stuck_out_tongue:

In a Go program, a long-running CPU-bound goroutine might (but not necessarily will - hence the “partial” qualifier) be involuntarily paused in favour of other goroutines. That to me qualifies as preemption.

I do agree with you though that partial preemption is ultimately cooperative, since under some conditions a goroutine can grab a scheduler and hold on to it forever.

4 Likes