Skip to content
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: inlined messaging is unclear when inlining functions from other packages #37704

snadrus opened this issue Mar 5, 2020 · 1 comment


Copy link

@snadrus snadrus commented Mar 5, 2020

$ go version
go version go1.14 darwin/amd64


What did you do?


package main

import (

func main() {
	os.Stdout.WriteString("Name: ")
	name, _ := bufio.NewReader(os.Stdin).ReadString('\n')
	os.Stdout.WriteString("Hi " + name)
go build -gcflags='-m' main.go


go build -gcflags='-m -l' main.go

What did you expect to see?

Nothing moved to heap for both.

What did you see instead?

The inlined version moved an allocation to heap while the non-inlined version did not.
The relevant part of -gcflags="-m -m":

./main.go:10:28: make([]byte, bufio.size) escapes to heap:
./main.go:10:28:   flow: {heap} = &{storage for make([]byte, bufio.size)}:
./main.go:10:28:     from make([]byte, bufio.size) (non-constant size) at ./main.go:10:28

It appears the const that's passed-in becomes non-const or isn't realized to be const because of the passed-in indirection. The inlining part of the output:

./main.go:10:28: inlining call to bufio.NewReader func(io.Reader) *bufio.Reader { return bufio.NewReaderSize(bufio.rd, int(4096)) }
./main.go:10:28: inlining call to bufio.NewReaderSize func(io.Reader, int) *bufio.Reader { var bufio.b·4 *bufio.Reader; bufio.b·4 = <N>; var bufio.ok·5 bool; bufio.ok·5 = <N>; bufio.b·4, bufio.ok·5 = bufio.rd.(*bufio.Reader); if bufio.ok·5 && len(bufio.b·4.buf) >= bufio.size { return bufio.b·4 }; if bufio.size < int(16) { bufio.size = int(16) }; var bufio.r·6 *bufio.Reader; bufio.r·6 = <N>; bufio.r·6 = new(bufio.Reader); bufio.r·6.reset(make([]byte, bufio.size), bufio.rd); return bufio.r·6 }
./main.go:10:28: inlining call to bufio.(*Reader).reset method(*bufio.Reader) func([]byte, io.Reader) { *bufio.b = bufio.Reader literal }
./main.go:10:49: inlining call to bufio.(*Reader).ReadString method(*bufio.Reader) func(byte) (string, error) { var bufio.bytes·5 []byte; bufio.bytes·5 = <N>; var bufio.err·6 error; bufio.err·6 = <N>; bufio.bytes·5, bufio.err·6 = bufio.b.ReadBytes(bufio.delim); return string(bufio.bytes·5), bufio.err·6 }
Copy link

@cherrymui cherrymui commented Mar 6, 2020

The allocation is from the inlined function in the bufio package. When it is inlined into main, the message shows up when compiling main. When it is not inlined, it still allocates, inside the function bufio.NewReader. You don't see the message when compiling main, but it still allocates.

Maybe the message could be more clear for inlined functions?

@toothrot toothrot changed the title Inlining caused more heap allocations than non-inlining. cmd/compile: Inlining caused more heap allocations than non-inlining. Mar 9, 2020
@toothrot toothrot changed the title cmd/compile: Inlining caused more heap allocations than non-inlining. cmd/compile: inlined messaging is unclear when inlining functions from other packages Mar 9, 2020
@toothrot toothrot added this to the Backlog milestone Mar 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants