-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: storing zero value into interface should not allocate #71323
Comments
Related Issues
Related Code Changes (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
This would be in
That would be efficient at runtime. How often does this come up? It seems like a pretty rare thing. |
Hi @dsnet, as you're probably aware, for basic types like strings/ints/floats, the runtime already does avoid allocations for interface conversions by dynamically detecting the zero value. I think the runtime does not do that for structs, though. One thing is that re-using the runtime's Separately, I think your example might be addressed by #62653, which is a more general solution that does not rely on whether or not the struct value is the zero value. (See intro comment in #62653, or #8618 (comment) for some related context). One question for you: as you were thinking about writing up this issue, are most of your real-world use cases for something like this issue really looking to store something in a global interface value (as shown in your simple benchmark), vs. is it more often trying to avoid an escape to the heap for something that could be otherwise stack allocated? In any event, it happens that I was separately looking into a more narrow case of statically detecting struct literals being used in interface conversions, which I think might address your specific example (more narrowly than #62653 would). I'll take a look at your example in that context. |
Maybe, it is always not a good idea to store big structs in interfaces. var sinkAny any = &tar.Header{}
{
*sinkAny.(*tar.Header) = tar.Header{}
} |
As a quick experiment I ran this snippet on each go/ssa basic block b over non-test code in std and cmd/...:
and it turned up this histogram of operand types for a MakeInterface operation with a "constant" zero operand:
So Struct is actually surprisingly common (though I suspect many are zero-sized structs). The file is attached, with approximate file/line/column info for some instances. |
Slices and most arrays are also non-small-size types. Just realized that OP's suggestion is dangerous? It is possible that I'm wondering that whether or not the case is similar to |
Er, my concern posted in the last comment is not valid. |
I have a first cut of statically detecting a composite value can be represented by all zeros, and if so, use a pointer to
I wouldn't be surprised if I'm currently doing something in the wrong spot or the wrong way, but I'll try to clean it up and send a CL for consideration in the not too distant future. The change uses ir.IsZero and is mostly in walk. It builds on some things I had been experimenting with a few months ago around improving how escape analysis treats local variables that flow from literals, especially when they are used as length/capacity arguments to make or in interface conversions (#71359). |
Go version
go1.23.5
Output of
go env
in your module/workspace:What did you do?
I ran this benchmark:
What did you see happen?
I saw these results:
What did you expect to see?
I expected to see zero allocations in both cases.
In #33136, we optimized
reflect.Zero
to use a zero buffer of sufficient size to back the zero value of most types.It seems to me that we could do the same trick for the non-reflect equivalent of storing a zero value into an interface value, where the data pointer in the interface value points to some shared zero buffer. This can be done in two ways:
Of course in both cases, you'll need to be careful since we're talking about a stricter definition of "zero" where the memory is equivalent to be all zeros.
The text was updated successfully, but these errors were encountered: