good practice or premature optimization

274 views
Skip to first unread message

Nico Braun

unread,
Oct 9, 2024, 11:51:02 PM10/9/24
to golang-nuts
Hi, recently I became very self aware of potential performance implications my code might have.

In go there are a few key concepts, like escape analysis and bound checks. If you check the standard library, you can see it was coded with micro optimizations. 

For example, disabling bound checks in some methods, by doing something `like _ = s[10]`.

Or trying to use function arguments that they will likely end up on the stack and not on the heap, by playing the escape analyzer. I.e. pass buffer to io.Reader. Or sometimes, dont pass interface because it is hard for the compiler to understand that the interface doesnt escape.

I wonder, if I code like this, is this considered premature optimization. Or is more like good habbit?


Ian Lance Taylor

unread,
Oct 10, 2024, 12:14:29 AM10/10/24
to Nico Braun, golang-nuts
In the standard library it's only done with benchmarks and profiles
that show that it makes a difference. So I would say that it's not
premature optimization, it's just optimization.

Doing that kind of bounds check avoidance in brand new code without
benchmarking or profiling might be reasonably called premature
optimization.

Ian

tapi...@gmail.com

unread,
Oct 11, 2024, 2:34:00 AM10/11/24
to golang-nuts
On Thursday, October 10, 2024 at 11:51:02 AM UTC+8 Nico Braun wrote:
Hi, recently I became very self aware of potential performance implications my code might have.

In go there are a few key concepts, like escape analysis and bound checks. If you check the standard library, you can see it was coded with micro optimizations. 

For example, disabling bound checks in some methods, by doing something `like _ = s[10]`.

The line is not a no-op. It makes bound checks in advance to remove more checks.

Nico Braun

unread,
Oct 13, 2024, 2:22:48 AM10/13/24
to golang-nuts
Hi, I was under the impression that this, ` _ = s[10] `, happens at compile time. But that probably doesnt make sense. We dont know the length of all slices at compile time. 

Then, what is this actually improving? Does the compiler see there will be a bound check, so it doesnt produce instructions for more bound checks? So the assembly or bytecode will be smaller.

Axel Wagner

unread,
Oct 13, 2024, 7:13:57 AM10/13/24
to Nico Braun, golang-nuts
If you write `_ = s[10]` and len(s)<11, that line will panic. So after that line, the compiler can assume that len(s)>=11 and omit bounds check for smaller indices.
That is, if you write

f(s[0])
f(s[1])
f(s[10])

That will be 11 bounds checks, as depending on what exactly len(s) is, a different line must panic. But if you write

_ = s[10]
f(s[0])
f(s[1])
f(s[10])

That will be 1 bounds check, as only one of the lines *can* panic - the first.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/66f9b041-1857-470f-b6c3-ce91a6126c01n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages