5 ms·
I normally hate it when people immediately trot out the old "premature optimization" quote, but it really applies here. Please don't go around naming all your
by edsrzf 9y ago
I normally hate it when people immediately trot out the old "premature optimization" quote, but it really applies here.
Please don't go around naming all your returns just because today's compiler happens to generate better code with them. This is a compiler issue that I'm confident will be fixed one day, especially if you do the right thing and file an issue.
But by all means, if you're profiling and your inner loops are actually slowed down by this, then make the change. And add a comment so that someone might be able to change it back some day when the compiler's improved.
- obstinate 9y agoI dunno. A 30% code size win is non-trivial. I'm all for filing an issue first and seeing how likely it is that there is uptake from the dev team and desire to fix the problem. However, if no fix is forthcoming . . . code size has fairly well known effects on performance.
- gizmo686 9y agoA 30% code size reduction in code that does little other than construct and return a value. I have certainly seen individual functions where this is the case, but across an entire program, you will not get anywhere near 30% size reduction. Having said that, this is certainly something that should be fixed in the compiler. On a related note, in the final assembly, the compiler could also have optimized the 4 RETs into 1, then optimized away all of the conditionals, turning the sample code into the equivilent of "return objectInfo()"). Of course, in a real example, these optimizations would not be possible; but they do show that these reduced cases are not the best way of benchmarking performance.
- lobster_johnson 9y agoFixing it in the compiler will fix it for everyone, however, which is a big argument for fixing it upstream.
- pjmlp 9y agoUnless it actually impacts the use case of the application, and has been confirmed by a profiler that is indeed the case, it is just cargo cult optimizations.
- bradfitz 9y agoI filed a Go bug: https://github.com/golang/go/issues/20859 https://github.com/golang/go/issues/20859 We should just fix the compiler.
- runeks 9y agoI'm surprised Go doesn't compile down to an IR language where these differences in syntax are represented in a single manner. Seems like different ways to write the same thing.
- weberc2 9y agoI'm pretty sure Go does compile down to an IR, but it's little more than an abstraction over different architectures. I could be wrong.
- hornetblack 9y agoOriginally it compiled to Plan9 assembly which is cross platform. They have an SSA backend for some architectures now.
- weberc2 9y agoI thought the SSA backend was not replacing the Plan9 assembly, but that it was a phase that happened before the assembly was output (presumably SSA is a phase and not an IR?).
- hornetblack 9y agoOh. That actually make more sense.
- bradfitz 9y agoIt increasingly does. But it's been a process. Go 1.5 was the first self-hosting release, with the Go compiler auto-translated from C to Go. But it was still fundamentally Ken's C compiler in Go syntax. Every release since (Go 1.6, Go 1.7, Go 1.8, Go 1.9) has been cleaning it up and making it more Go like and less C like. Meanwhile, the backend was also retrofitted. Go 1.7 included an SSA backend for amd64 (https://golang.org/doc/go1.7#compiler https://golang.org/doc/go1.7#compiler). Go 1.8 included it for all architectures and added more SSA goodness. Go 1.9 adds yet more, but some things are still not pushed down into SSA as well as they could be. (e.g. https://github.com/golang/go/issues/5147#issuecomment-247685599 https://github.com/golang/go/issues/5147#issuecomment-247685...) Nowadays we can add optimizations much more easily, including writing matching rules like in https://github.com/golang/go/blob/master/src/cmd/compile/internal/ssa/gen/generic.rules https://github.com/golang/go/blob/master/src/cmd/compile/int... Meanwhile the whole toolchain keeps getting cleaned up and more hackable. In Go 1.9, the compiler is now parallelized, which would've been impossible earlier. (https://tip.golang.org/doc/go1.9#parallel-compile https://tip.golang.org/doc/go1.9#parallel-compile) So, it keeps improving. Just remember the Hello World compiler we started with. Also amusing in retrospect is that when Go first came out, despite having a very basic compiler at the time, people coming from scripting languages thought we were so fast.
- wlll 9y agoI think accusations of premature optimisation might be a little unfair here. Ignoring the style issues for a second (I'll pick that up later), if I'm looking at some code and there are two equally viable alternative ways of writing it, one of which saves a chunk of memory* or is faster then it's just perverse to choose the path of larger/slower code. I do this with regular expressions/string functions. I see people use regexes a lot, but the tool I reach for first when doing string operations are the built-in string functions, eg. https://golang.org/pkg/strings/#Contains https://golang.org/pkg/strings/#Contains or https://ruby-doc.org/core-2.4.0/String.html#method-i-start_with-3F https://ruby-doc.org/core-2.4.0/String.html#method-i-start_w.... I'm not optimising, I'm just not de-optimising. Back to the style issue, at this point if you really feel strongly about the way it looks in the editor, or in documentation then I can see why you would choose one method over the other, choosing the less desirable, but theoretically faster code would absolutely be a case of premature optimisation. I personally don't have a particular preference either way however, and feel like the reasons outlined in the style guide are rather fragile. So ultimately, if I pick up some code full of named return values I don't think it would bother me, in the same way that code that uses none, or mixes them where someone thought it appropriate doesn't bother me either. * There may be benefits other than just disk/distribution size. Many years ago I read about the benefits of small binaries, something relating to CPU caches, though that may be out of date now and I forget the details.
- hyperpape 9y agoThe issue is that with the string/regex issue, there's a good reason that the string operation should be faster. Maybe a "sufficiently smart compiler" could optimize it in some cases of static regexes, but it's at least complicated. In cases where the regex is dynamically determined, even the sufficiently smart compiler probably can't optimize away the regex. In contrast, the case in this article seems like table stakes for an optimizing compiler. It's just not eliminating common subexpressions. There's no reason to contort your code around something that should automatically happen.
- wlll 9y agoWhen I've benchmarked regexes before (Ruby ISTR) there have been situations where the regex engine optimised the code to be comparable to string functions, I can't remember the details though. Just for fun I benchmarked =~ /\Asomething/ and start_with?("something"), a situation that seems could be optimisable by the regex engine, but the string function is still faster (Ruby 2.3.1): start_with: 5703143.1 i/s regex: 2821224.4 i/s - 2.02x slower That aside: > There's no reason to contort your code around something that should automatically happen. Absolutely, but it's a question of style at that point. "Contorting your code" suggests using a less desirable style/syntax for some gain, and I'd agree would be premature optimisation. If you're just making a choice between two styles that you consider to be pretty much equal then it's just pragmatic. edit: Forgot to add, yes, I agree that this should happen automatically in the compiler :)