3 ms·
The reason cgo is (relatively) slow is small stacks, not M:N threading. Small stacks (and M:N threading) are needed to efficiently implement tens of thousands
by kjksf 7y ago
The reason cgo is (relatively) slow is small stacks, not M:N threading.
Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines.
CGO is slow mostly because it needs to switch to a larger stack when calling a C function.
It's a trade-off.
A different Go implementation could make Goroutines map 1:1 to threads and have fast cgo calls at the expense of slow goroutines.
Rust is not exempt from those trade-offs. They chose fast FFI and smaller runtime. They paid with slow threads.
Async/await promises to be the best of both worlds but it comes at a cost of great complexity, both for the programmer and the implementor.
At the end of the day under the covers it's just threads that need to be managed in a complex and often invisible way plus a complex rewrite of your straightforward code into a mess of a state machine.
I can confidently say that learning to use goroutines took 10x less time than learning async/await in C#.
I understand goroutines better than I ever understood async/away.
- pcwalton 7y ago> Small stacks (and M:N threading) are needed to efficiently implement tens of thousands of goroutines. Tens of thousands of threads are no problem with 1:1 threading on Linux. > They paid with slow threads. I would not call 1:1 threads "slow threads". If they were slow, then the 1:1 NPTL would have not defeated the M:N NGPT back in the day when this was being debated in the open source OS community. > complex rewrite of your straightforward code into a mess of a state machine. The entire point of async/await is that you don't have to do a complex rewrite of your straightforward code. It remains straightforward, and the compiler does the transformation for you.
- Thaxll 7y ago> tens of thousands of threads are no problem with 1:1 threading on Linux Yes it's a problem, even on modern kernel, memory, context switch ... there is a reason why high performance code uses small thread pool.
- masklinn 7y agoGiven the context, it's not a memory problem was implied, because small stacks are not actually relevant, because C stacks are not committed upfront (at least on unices, not sure about linux). So your threads are more likely to take up a page each (plus kernel datastructure overhead) than the 8MB allowed to a C stack.
- littlestymaar 7y ago> It's a trade-off. Yes, That's exactly my point. > I can confidently say that learning to use goroutines took 10x less time than learning async/await in C#. It's a matter of preferences, I've always preferred async/await to threads because you don't need to juggle with channels and you're way less likely to cause a deadlock. > it comes at a cost of great complexity, both for the programmer and the implementor. Is that really harder to implement than a M:N runtime like Go's? > The reason cgo is (relatively) slow is small stacks, not M:N threading. You're picking nits here. Without small stacks there would be no point using M:N threading in Go… And Cgo is not only relatively slow: most of the time it is slow enough to destroy all performance benefit of calling a FFI function. It's a pretty big deal.