Hacker News new | past | comments | ask | show | jobs | submit login

For some scenarios, the implementation code will be quite complicated if only mutexes are used, whereas the implementation will be quite simple by using channels.

I think your frustration comes from you wanted to use channels for any scenarios. This is not recommended too. https://github.com/golang/go/wiki/MutexOrChannel




It fails to mention the performance penalty with channels.


For some scenarios channels and mutexes are both suitable for, mutextes are a bit more performant than channels. If you do care about the performance penalty, just choose mutexes. But the for scenarios mutextes are incapable of, still using mutexes is surely not a good idea.


This would be a good thing to add to the reference.


Dunno. Tell people "channels are about 3 times slower than mutexes" and watch them scramble the hell out of their program trying to avoid channels, when the reality is "in general, both of them are fast enough that they will not be the bottleneck on your program".

In general (not just Go!), don't send tiny amounts of work across any sort of internal boundary (goroutine, thread, spark, green thread, whatever they call it). The amount of work you send should significantly exceed the costs of sending it. Follow this advice and the perf differences between mutexes and channels will almost certainly not be relevant; fail to follow it and neither of them will be fast enough. I don't think there's actually a lot of programs in the wild where the performance difference between the two would be the make-or-break difference. Non-zero, but not many. In practice it's pretty clear developers will spend much more time worrying over it than is justified.

(A common benchmark I see new programmers apply to any language that claims to be good at multithreading is to try to "parallelize" the act of adding a few million integers together by sending individual integers or addition problems out to threads, and wondering why it's 10-100 times slower even though all my CPUs are at 100%, so why does multithreading suck so hard in this language? The problem is that no matter how cheap the send operation is, it's going to be dozens or hundreds of operations, whereas a single integer addition is generally a single cycle, or possibly, amortized to less than that depending on how good your compiler is. You just need to be sure to send units of work larger than the cost of sending them, which is generally not that hard. This isn't just Go, I've seen this charge leveled at Haskell, Erlang, and Python's multiprocessing too, and I'm sure others have seen it in their own communities. It's a very common mistake.)


The amount of work you send should significantly exceed the costs of sending it.

Jerf, you did it again! This is gold! Succinct and to the point.

I'm going to think on this one.


This implies that you know the "costs of sending it."


For channels and other things in the local OS process, you should have a good idea. Give or take being in major swap problems, etc., but I think of that as an "already lost" situation; at that point the problem isn't the expense of moving things between threads or local processes anyhow.

When you get out into discussing network matters, it gets a lot fuzzier. You may "know" that you're only .025ms away from something in some specific system, but your TCP-based API doesn't necessarily "know" that and will happily use the exact same code to do something that takes 4 orders of magnitude larger. That's enough difference to be problematic.


'Send'ing things via a Go channel is all in the same process, between goroutines (sometimes between threads).


Because there is no generic penalty, and worrying ahead of having a problem to solve sounds like a terminal case of premature optimization.


Not sure if it's the case nowadays, but Go channels were historically around 4x slower than the equivalent mutex-based code. This is a Big Deal™ if you're writing performance sensitive code or in a hot loop.

https://www.jtolio.com/2016/03/go-channels-are-bad-and-you-s...

https://www.datadoghq.com/blog/go-performance-tales/


Comparing a FIFO internally wrapped in mutexes and conds, designed to pass messages, to a single mutex makes very little sense. Of course a channel is slower than one of the bare primitives used to construct it!

The proper question to ask is whether your application (or your programmer) lends itself with the CSP paradigm or not, and whether this allows you to write simpler, more robust code.

Extremely performance sensitive code will always need to be written In lower level paradigms, using e.g. atomics directly - this doesn't matter for most code though. And to be frank, extremely performance sensitive code is past the capability of Go for quite a few reasons.


I've had the opposite happen, where because of mindsets like this, that it doesn't get properly discussed and going in blind having to deal with it later in a case where it was clear that it would matter.


The mindset is still correct - it depends too heavily on your usecase to make a generic statement.

For anything performance sensitive, the only thing that matters is to profile your code.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: