escape analysis question

172 views
Skip to first unread message

burns...@gmail.com

unread,
Mar 4, 2020, 4:58:37 PM3/4/20
to golang-nuts
Hi All,

I am trying to debug why a byte slice is escaping in my program. I have a small reproducible example here:

% cat escape.go
package main

func main() {
x := make([]byte, 5)
y := new([]byte)
*y = x
nothing((*y)[3])
}

func nothing(b byte) {}
% go tool compile -m -m -l escape.go
escape.go:4:11: make([]byte, 5) escapes to heap:
escape.go:4:11:   flow: x = &{storage for make([]byte, 5)}:
escape.go:4:11:     from make([]byte, 5) (spill) at escape.go:4:11
escape.go:4:11:     from x := make([]byte, 5) (assign) at escape.go:4:4
escape.go:4:11:   flow: {heap} = x:
escape.go:4:11:     from *y = x (assign) at escape.go:6:5
escape.go:4:11: make([]byte, 5) escapes to heap
escape.go:5:10: new([]byte) does not escape

It seems to me like neither x nor it's backing array should escape, but I'm having trouble figuring out why it's flagged as escaping from the debug output.

% go version
go version go1.14 darwin/amd64


Any help would be appreciated.

Ethan

Kevin Chowski

unread,
Mar 4, 2020, 6:44:35 PM3/4/20
to golang-nuts
Slightly more minimal, in my testing it seems that the call to 'nothing' is not needed.

I do not quite know why, but these two lines seem to show how the compiler is reasoning about this escape:

escape.go:4:11:   flow: {heap} = x:
escape.go:4:11:     from *y = x (assign) at escape.go:6:5

I do not know why it thinks assigning to '*y' is equivalent to assigning to the heap; later it even mentions that `new([]byte) does not escape`, and that is the definition of 'y'.

Sorry I'm not more helpful, I looked into this a bit more myself and also came up without any good answers.

Ethan Burns

unread,
Mar 4, 2020, 6:52:01 PM3/4/20
to Kevin Chowski, golang-nuts
Thanks for looking into it and simplifying the example!

Just to explain, I added the call to nothing(), because I was worried that otherwise the result would be recognized as unused and the entire code would be optimized away. Good to know it's not relevant to reproduce. Thanks again.

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/2s0_gQjR7yE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a315ea46-f8ac-4a8f-bc43-c2b16367e72f%40googlegroups.com.

tokers

unread,
Mar 5, 2020, 4:20:11 AM3/5/20
to golang-nuts
This is a known deficiency of Go's escape analysis, which is recorded in this doc: https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/view#

Ethan Burns

unread,
Mar 5, 2020, 5:58:38 AM3/5/20
to tokers, golang-nuts
Thanks. I'll give that doc a read. Just to make sure, I noticed that the doc is dated 2015, but the escape analysis implementation seemed to change just recently from that implemented in esc.go to a new one in escape.go. Dose the doc still apply to the new implementation?

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/2s0_gQjR7yE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Ian Lance Taylor

unread,
Mar 5, 2020, 1:56:15 PM3/5/20
to Ethan Burns, Matthew Dempsky, tokers, golang-nuts
[ +mdempsky ]
> 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/CAGE%3DEi2Bdzydu%2BzGHA0-xmMd0NTrBePBcTFAAvm1A-1RLiaa9Q%40mail.gmail.com.

Matthew Dempsky

unread,
Mar 5, 2020, 2:17:18 PM3/5/20
to Ian Lance Taylor, Ethan Burns, tokers, golang-nuts
Some of the issues in that doc should be addressed now (e.g., the first two), but the "Assignment to indirect escapes" case still applies.

The issue here is we don't do any points-to analysis during escape analysis, so we conservatively assume "*p = x" might assign x to the heap.

Ideally, I think we fix this by moving escape analysis to SSA.

In the meantime, what might be reasonable is to at least recognize assignments through pointer variables that are initialized and then never re-assigned. We already recognize variables of this form for recognizing when we can inline calls to closures that were assigned to local variables.
Reply all
Reply to author
Forward
0 new messages