go: cmd/compile: 1.15 heap allocations regression when calling Write on os.Stdout

$ go version
go version go1.15.2 linux/amd64

$ uname -a
Linux gauss 5.7.0-2-amd64 #1 SMP Debian 5.7.10-1 (2020-07-26) x86_64 GNU/Linux

I have a program that shall not heap-allocate in its main loop, with a test checking that. When I re-compiled the program with Go1.15, the test started failing. This is the offending line according to mem profile data:

  os.Stdout.Write([]byte("\033[2J\033[1;1H"))

Ignore the string literal cast to []byte, it’s a red herring. Here’s a reproducer:

package p

import "os"

func f() {
	os.Stdout.Write([]byte{'h', 'e', 'l', 'l', 'o'})
}

Go1.14:

$ go tool compile -m test.go
test.go:5:6: can inline f
test.go:6:24: []byte literal does not escape

Go1.15:

$ go tool compile -m test.go
test.go:5:6: can inline f
test.go:6:24: []byte literal escapes to heap

git bisect points to 8c1db77a92b1d17d3fe07999c5f20602a2080be9, but I don’t know if that makes sense.

cc @dr2chase @randall77 @ianlancetaylor

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 31 (21 by maintainers)

Commits related to this issue

Most upvoted comments

Clearly we should replace the loops with goto statements.

We should find and fix that bug. Inlining goto but not for creates a bit of a perverse incentive…

The plan here is to try to fix this in the compiler, but if we get to the freeze without that landing, we’ll just forward-port the 1.15 fix.

Given that we’ve backported a fix for this issue to Go 1.15, I believe we should not release Go 1.16 without fixing this (or re-visiting this in some way), so marking as a release-blocker.

I’ve landed all the individual compiler optimizations to fix this, but it’s proving tedious to write a test that shows the original test case involving os.Stdout.Write has actually been fixed. E.g., js/wasm and apparently Windows also still escape, but at least js/wasm also escaped in Go 1.15. I haven’t looked into Windows.

It should be a straightforward task for someone to take CL 262678 and amend it. Probably it just needs to check runtime.GOOS == "windows".