
Performance of green threads and why it matters - rumcajz
http://250bpm.com/blog:81
======
hellofunk
>First of all, go() statement in Go language does parallelism in addition to
simple green-threading. With all the talk about 'concurrency is not
parallelism' that seems to be part of Go's DNA, I find the design decision to
support both using a single statement a bit weird.

Have to agree on this, and often wonder the same thing.

~~~
themartorana
I'm having a hard time understanding where you would want concurrency without
the benefit of parallelism where available? I also personally consider the
idea of single-core concurrency as "not parallelism" to be semantics. It may
not be _truly_ parallel, but both routines are getting CPU time in the same
algorithm, so, in terms of programmatic considerations, to me the two (at
least with Go) are basically the same.

~~~
justincormack
So you don't need locking.

~~~
wyager
Non-parallel (perpendicular?) green threads are semantically indistinguishable
from parallel green threads. If you need locks with parallelism, you need them
with green threads. Any locking unique to parallelism is handled by the
runtime.

------
jeffreyrogers
Here's a good (introductory) resource on implementing green threads:
[http://c9x.me/art/gthreads/intro.html](http://c9x.me/art/gthreads/intro.html).
It's helpful for learning how they work in practice.

Are people running into performance issues with green threads in practice? It
seems like they're already pretty performant, particularly if you're using
them more as an abstraction for concurrency than as a way to get parallelism.
There are lots of problems that are trivial to solve with green
threads/coroutines but that are very difficult without them. If you really
care about performance you probably shouldn't be using green threads at all
but should instead be running separate processes on dedicated cores. Green
threads also have the advantage over kernel threads in that they don't require
the overhead of a kernel context switch, since the context switch can be done
in userspace, which requires saving much less context and also affects your
caches less.

~~~
zzzcpan
> There are lots of problems that are trivial to solve with green
> threads/coroutines but that are very difficult without them.

Name at least one that cannot be solved better without them.

~~~
rumcajz
Network stacks. And pipelines in general.

~~~
zzzcpan
Be specific. Network stacks and pipelines are easier even with the most basic
event loop, because you simply don't have to think about concurrent memory
access whatsoever. But you do with green threads and coroutines.

~~~
barrkel
Event loops lose your call stack; you need to rewrite your program as a state
machine so you know where to pick back up; or you need to rewrite your program
in continuation passing style with callbacks, like JavaScript; or you automate
that CPS transform, and you've just reinvented green threads again.

~~~
Matthias247
I agree with what you (and the others) say.

Regarding green threads and state machines I would however add that while
green threads allow to ditch some state machines (e.g. ones that wait until a
complete packet was received) you won't get rid of all of them, e.g. you will
still need state machines for lots of protocol implementations. E.g. if you
are implementing the websocket protocol or HTTP/2, you have some interaction
between incoming data, data that must be sent out and requests from the
[library] user. The state of the connection depends on all of these, so you
need some kind of connection state machine which would run most likely in it's
own green thread (in addition to a sending thread and a receiving thread and a
user thread). And now you have to implement clean synchronization between all
of those threads. The lack of necessary synchronization (and the ability to
observe a huge amount of state at once without danger) can make the
implementation a little bit more easy in my experience. But here I also have
to agree with strmpnk that a good design is necessary for both approaches, and
accessing lots of shared mutable data in multiple callbacks is probably also
not the cleanest approach.

------
halayli
Goroutines use segmented stacks that allows them to grow dynamically as
needed. so 4k goroutines != 4gb of ram. They currently start at 8k and grow as
needed but copies are incurred to keep it contiguous.

In lthread I preallocate fixed size 1mb stack but madvise after a coroutine
yields if the stack shrunk. No copies are needed but it does consume the vm
address space.

~~~
ominous_prime
Go hasn't used segmented stacks in quite a while. Go now has 2k stacks and
uses stack copying to grow.

------
bobinator606
we built a green threads implementation for VAX/VMS in 1984 with pre-allocated
stacks because performance. the key is to put guard pages in between the
stacks to protect from stack overruns.

------
zzzcpan
There is a very big difference between implicit flow control, that you have
with green threads and explicit one, that you have with "reinvented green
threads", as you call them. First one will force you to think about
synchronization to access your memory, but the second one - won't. It will
also let you do clean cancellation, etc., that you won't be able to do with
green thread.

Downvote all you want.

~~~
jcoffland
Go is an interesting language but the fanboys on HN tend to down vote any
criticism. Same goes for the other golden child, Rust.

~~~
dang
This breaks the site guidelines by calling names ('fanboys') and complaining
about downvoting.

The problem with comments like this is that they degrade the discourse even if
they're true.

[https://news.ycombinator.com/newsguidelines.html](https://news.ycombinator.com/newsguidelines.html)

