Live data from Hacker News

Practices for writing high-performance Go

github.com

61–70 of 102 posts

Re: Practices for writing high-performance Go

#61
post #34

Earlier quoted context omitted.

All over my profiler. Go can deal with something embarrassingly parallel, same as any other language, but try getting it to scale up to high core counts with small RPCs is impossible, for the reasons the OP mentioned: you can't avoid its global allocator and you don't control the scheduler either. You will spend all of your CPU time in runtime.findrunnable and runtime.mallocgc.

I guarantee you the "little bit of planning" you're doing in C++ is far greater than the equivalent planning in Go to avoid the global allocator in your goroutines (i.e., allocate on the stack, use object pools, etc). I'm sure you still won't get to the same performance ceiling that C++ allows, but it doesn't mean "Go is bad at concurrency".

The philosophy of Go, as far as I can tell, is opinionated simplicity. In this way, it is fantastic at concurrency.

It gives you a simplified fork in goroutines, a way to safely pass by value or signal between these through channels, and structures like select to psuedo randomly deal with race conditions.

That stuff is all awesome!

But when you are talking about performance, opinionated simplicity is a bad philosophy. You are going to want the finer grained control the poster is asking for, and which Go deliberately doesn't allow for. C, C++, and Rust will always have a speed advantage because they lack the overhead of the GC and were designed with allowing the developer minute control of the system, which is the space to make such optimizations.

That said, opininated simplicity means every Go codebase I drop into looks roughly the same. That is not true in the above langauges, precisely because they allow for more control.

To me, Go's ideal use case is the domains of Java, Python, NodeJS, and even Elixir -- where it has a performance edge in many cases and where its consistant style really shine.

All that to say, Go is bad at performance optimized concurrency, as designed.

Re: Practices for writing high-performance Go

#62
post #24

Earlier quoted context omitted.

High performance is a very vague terms now days, there are company that have Google scale problems that don't use C++ as main language ( Nerflix Uber ect ) any modern runtime can do "high performance" especially for backend applications. YouTube primary language is Python for instance.

Netflix OK but Uber? They did 4 billions rides in 2017. Thats naivly about 130 rides per second with nice parallelism due to locality of the physical rider. That's not an insane amount of data crunching.

In my experience, most non-trivial sites are similar to icebergs of code - users might see 5% of the codepath in normal usage for what they want, but there's boatloads of OLAP, data analysis, instrumentation, error handling, and reporting being done on those transactions to help make that 5% both more profitable and reliable.

Re: Practices for writing high-performance Go

#63
post #58

any thoughts on whether to use values or pointers to large structs? in practice I haven’t seen any major performance overhead when passing values about.

I also wonder about this. I think some benchmarks are in order, with checks for the impact of escape analysis/copy to heap.

Re: Practices for writing high-performance Go

#64

Earlier quoted context omitted.

The Go authors have steadfastly refused to offer users any means of writing a CPU-local freelist, even though the utility of such things is obvious and evidenced by the fact that they use such things all over the runtime package. They just think that _you_ are too stupid to be allowed to do such a thing. Honestly with the attitude that the Go authors treat their users I don't know why anyone tries to write high perfo…

Honestly with the attitude that the Go authors treat their users I don't know why anyone tries to write high performing code in that language. C++ is there, after all. I work in C++. I'm sometimes surprised at the way C++ treats its users. There seems to be a culture of pre-optimization. It's hard to write the most abstract application code without constantly thinking about performance under the surface. That's baked…

It is a trait inherited from the C culture, although in C it is even worse, micro-optimizing every line of code as it is being written.

A C dev would start cold sweating has s/he types virtual, or operator something().

Re: Practices for writing high-performance Go

#65

Earlier quoted context omitted.

"The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt." – Rob Pike

That is taken out of context. Practically all Google server code is written in C++ or, at a much smaller scale, Java. Go is used for logs analysis, internal services, monitoring and automation, etc. Nobody at Google reaches for Go when they are thinking of high performance nor would anyone try to optimize a large service in Go. They would just write it in C++ instead as soon as it starts to cost non-trivial amounts o…

It is not out of context, it was stated just like that on a talk given by Rob Pike at Microsoft, it is available on Channel 9.

Re: Practices for writing high-performance Go

#66
post #40

Earlier quoted context omitted.

Disagree. I can write a server in C++ that, with careful thought and a bit of planning, will be able to exploit the resources of the kind of 88-core dual-socket machines that are mainstream today. No amount of planning will allow me to write a Go program that does the same thing on the same machine. Small amounts of concurrency might seem easy in Go but lots of concurrency is hard.

"I can write a server in C++ that, with careful thought and a bit of planning, will be able to exploit the resources of the kind of 88-core dual-socket machines that are mainstream today." This is downvoted grey as I write this, and as someone who has been called a "Go shill" on occasion... it's exactly right. Go is a decent language for writing code in a fairly straightforward manner and getting pretty good performa…

How would Rust compare?

Re: Practices for writing high-performance Go

#67
post #66
post #40

Earlier quoted context omitted.

"I can write a server in C++ that, with careful thought and a bit of planning, will be able to exploit the resources of the kind of 88-core dual-socket machines that are mainstream today." This is downvoted grey as I write this, and as someone who has been called a "Go shill" on occasion... it's exactly right. Go is a decent language for writing code in a fairly straightforward manner and getting pretty good performa…

How would Rust compare?

The benchmark game puts c, rust, and c++, in that order, roughly on par in performance, with go being about 2-3x slower. No idea if that's accurate. Sampling bias means people who like performance are optimizing the languages used for performance, and people who just like to get something working quit after the first benchmark in go or python is finished. https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Re: Practices for writing high-performance Go

#68
post #66
post #40

Earlier quoted context omitted.

"I can write a server in C++ that, with careful thought and a bit of planning, will be able to exploit the resources of the kind of 88-core dual-socket machines that are mainstream today." This is downvoted grey as I write this, and as someone who has been called a "Go shill" on occasion... it's exactly right. Go is a decent language for writing code in a fairly straightforward manner and getting pretty good performa…

How would Rust compare?

Also, Dropbox rewrote the core stuff from go to rust when they needed more performance. So that is one example/anecdote.

Re: Practices for writing high-performance Go

#70
post #58

any thoughts on whether to use values or pointers to large structs? in practice I haven’t seen any major performance overhead when passing values about.

Passing pointers is typically a code smell in Go, given that the "don't communicate by sharing, share by communicating" hinges on copying values when passed into e.g channels so as not to have mutexes everywhere, which would defeat the purpose of such a design.

Not that you should not have mutexes in idiomatic Go, but they usually have to be warranted for.

Post reply on HN