Home > Blockchain >  What makes green threads slower for CPU bound tasks?
What makes green threads slower for CPU bound tasks?

Time:08-19

I recently came across some commentary on a forum about how green threads maybe cheap but are not good for CPU bound concurrent tasks. They gave Go as an example stating that using goroutines for CPU bound tasks is notably slower than the C/Java/Rust equivalent using raw threads (OS level threads).

I know that green threads are great in terms of efficiancy for IO bound tasks. But I did not know that they are not so great for CPU bound tasks. Is this true? If so, why?

CodePudding user response:

The advantage of green threads is that they avoid the expense of switching to the kernel on a (typical) thread switch. Likewise the cost of creating a green thread is (typically) smaller. So if your workload involves a lot of thread creation and/or switching then green threads may be advantageous.

But the flipside is that with pure green threads1 the threads all share a single core. Execution switches from one thread to another, but only one actually runs at a time. In order to get true parallelism (and make use of multiple cores), you need either regular threads or a hybrid of regular and green threads.

Also a typical green thread implementation doesn't allow a green thread to be preempted. (It is complicated and expensive to do in use-space.) So thread switching only occurs at points where the thread volunteers to switch; e.g. when waiting for a signal or a lock, performing an async I/O operation, etcetera.

Contrary to what you understand, pure green threads are NOT a good fit for blocking I/O. When a green thread makes a blocking I/O syscall to the kernel, there is no way to reschedule to another green thread. So you need a use-space library that will map the blocking I/O requests by the green threads onto asynchronous I/O requests using selectors or something. That adds complexity and performance overheads.

Of course ... the pro's and con's will depend on the minutiae of the actual threading design and implementation and how they interact with the operating system. That makes it difficult to generalize.


1 - I am treating this as definitional in the context of this answer. If the OS can allocate more than one core to a process, then by definition the OS needs to be aware of the threads ... and they are not pure green.

CodePudding user response:

Because green threads don't really run in parallel but by taking turns. Parallelism is achieved with asynchronous I/O. It's pretty much like cooperative multitasking on a single CPU.

Asynchronous I/O is non-blocking. It immediately returns when you call and signals a callback function whenever it finishes. This way, you can do other stuff while waiting for I/O to finish. Green threads use this feature, and run other waiting "green threads" while waiting for that I/O operation to complete.

Since green threads can only switch tasks during an I/O operation, a CPU-bound operation will essentially block the other green threads.

So, why are green threads better than regular threads? Because they're lean, so, far more scalable than regular threads for primarily I/O bound tasks. They're certainly not suitable for CPU-bound tasks.

CodePudding user response:

Green threads in a CPU-bound situation are equivalent to cooperative multitasking on a single processor. Cooperative multitasking requires a task to voluntarily yields its computation to give another task cpu time. This context switching causes L1/2/3 cache thrashing which is slower than the alternative which is to serially complete tasks.

Also on a single core machine, OS-level threads are just as slow as "green" threads on CPU bound tasks.

  • Related