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: generic function argument causes escape to heap #48849
Comments
This is expected. When compiling
The Note that we could resolve this if we were fully stenciling. But in our current implementation of generics (with gcshape stenciling and dictionaries) both |
This is getting beyond the scope of this issue, and probably well travelled ground (I haven't been following any CLs), but this makes me wonder about ubiquitous GC stenciling. I would agree that we don't want a special comment to enable full templating (a.k.a. monomorphisation) because then everyone will use it and we could end up just like Rust with bloated compile times and binaries. However it seems fairly clear to me that there are some situations where the templating overhead is small and the potential gains large. We could make a similar decision as we do when deciding whether to inline functions currently. Specifically, we can consider how to instantiate a function F with some set of type parameters [T₁, T₂, ...] with respect to some cost metric C(T₁, T₂, ...). A possible cost metric might be as the (estimated) code size of the function's code multiplied by the total number of instantiations of F (one instantiation for each unique set of type parameters to F). If the cost metric is below some threshold, we fully template the function; otherwise we use GC stenciling, or even full fully generic code (cheaper than reflect but not much) in extreme cases. One canonical "extreme case" is the case of unbounded types (e.g. https://go2goplay.golang.org/p/3kUZ6L8amfd) which would then run OK but be predictably costly) |
Thank you for the explanation, and the follow-up. FWIW the reason I tried this was the regexp package has three input variants: byte slice, string and io.Reader, so the expected number of instantiations is small and the expected benefit from inlining, not-escaping, etc., is relatively high. |
This example at least seems solvable with improved escape analysis. Right now |
That's not necessarily true. The caller might have |
True, but call-site sensitive escape analysis would help with some generic cases, and actually should help some non-generic cases as well. For example
This function cannot be inlined, so buf is always put on the heap (by the caller, or callers caller or whatever). But actually, it's safe to put buf on the stack if we know that the Reader doesn't hold onto it. But I digress. |
Change https://golang.org/cl/360015 mentions this issue: |
There was no way to use an interface because the methods on the Point types return concrete Point values, as they should. A couple somewhat minor annoyances: - Allocations went up due to #48849. This is fine here, where math/big causes allocations anyway, but would probably not be fine in nistec itself. - Carrying the newPoint/newGenerator functions around as a field is a little weird, even if type-safe. It also means we have to make what were functions methods so they can access newPoint to return the zero value. This is #35966. For #52182 Change-Id: I050f3a27f15d3f189818da80da9de0cba0548931 Reviewed-on: https://go-review.googlesource.com/c/go/+/360015 Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Moving to 1.20 milestone. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, needs generics.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
This program: https://play.golang.org/p/speaQxyFO4a
Compiled with
-gcflags "-m -m -l"
to show escape analysis.What did you expect to see?
What I get if
t
is declared as the concrete type*bar
:What did you see instead?
The text was updated successfully, but these errors were encountered: