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

runtime: don't allocate for non-escaping conversions to interface{} #8618

Open
randall77 opened this Issue Aug 29, 2014 · 10 comments

Comments

Projects
None yet
@randall77
Contributor

randall77 commented Aug 29, 2014

fmt.Fprintf("%d", 8)

Since all interface data fields are now pointers, an int must be allocated and
initialized to 8 so that it can be put in an interface{} to pass to Fprintf.

Since we know the 8 doesn't escape, we could instead allocate that 8 on the stack and
have the interface data word point to that stack slot.  To be safe, we can only do this
when the resulting interface{} doesn't escape.  We probably also need to be sure the
conversion happens at most once so the stack slot is not reused.

We could have a special convT2Enoescape call for the compiler to use when it knows the
result doesn't escape.  Maybe also convT2I, assertT2E, ...
@robpike

This comment has been minimized.

Show comment
Hide comment
@robpike

robpike Aug 29, 2014

Contributor

Comment 1:

Status changed to Accepted.

Contributor

robpike commented Aug 29, 2014

Comment 1:

Status changed to Accepted.

@griesemer

This comment has been minimized.

Show comment
Hide comment
@griesemer

griesemer Oct 1, 2014

Contributor

Comment 2:

Labels changed: added repo-main.

Contributor

griesemer commented Oct 1, 2014

Comment 2:

Labels changed: added repo-main.

@jeffallen

This comment has been minimized.

Show comment
Hide comment
@jeffallen

jeffallen Dec 10, 2014

Contributor

This thread explains how this issue causes 2 allocs on every call to os.(*File).Write.
https://groups.google.com/forum/#!topic/golang-nuts/0hfeLJP1LSk

Contributor

jeffallen commented Dec 10, 2014

This thread explains how this issue causes 2 allocs on every call to os.(*File).Write.
https://groups.google.com/forum/#!topic/golang-nuts/0hfeLJP1LSk

@josharian

This comment has been minimized.

Show comment
Hide comment
@josharian

josharian Mar 23, 2015

Contributor

Dmitry started this in CL 3503. Note that this requires improved escape analysis.

Contributor

josharian commented Mar 23, 2015

Dmitry started this in CL 3503. Note that this requires improved escape analysis.

@gopherbot

This comment has been minimized.

Show comment
Hide comment
@gopherbot

gopherbot commented Jan 24, 2017

CL https://golang.org/cl/35554 mentions this issue.

@navytux

This comment has been minimized.

Show comment
Hide comment
@navytux

navytux Apr 20, 2017

Contributor

For the reference until this is fixed some of us use ad-hoc printf-style mini language to do text formatting in hot codepaths without allocations. For example if in fmt speak you have

s := fmt.Sprintf("hello %d %s %x", 1, "world", []byte("data"))

the analog would be

buf := xfmt.Buffer{}
buf .S("hello ") .D(1) .C(' ') .S("world") .C(' ') .Xb([]byte("data"))
s := buf.Bytes()

It is a bit uglier but runs faster and without allocations:

pkg: lab.nexedi.com/kirr/go123/xfmt
BenchmarkFmt-4       5000000           246 ns/op          72 B/op      3 allocs/op
BenchmarkXFmt-4     20000000            57.9 ns/op         0 B/op      0 allocs/op

Details:

https://lab.nexedi.com/kirr/go123/commit/1aa677c8
https://lab.nexedi.com/kirr/go123/blob/c0bbd06e/xfmt/fmt.go

Contributor

navytux commented Apr 20, 2017

For the reference until this is fixed some of us use ad-hoc printf-style mini language to do text formatting in hot codepaths without allocations. For example if in fmt speak you have

s := fmt.Sprintf("hello %d %s %x", 1, "world", []byte("data"))

the analog would be

buf := xfmt.Buffer{}
buf .S("hello ") .D(1) .C(' ') .S("world") .C(' ') .Xb([]byte("data"))
s := buf.Bytes()

It is a bit uglier but runs faster and without allocations:

pkg: lab.nexedi.com/kirr/go123/xfmt
BenchmarkFmt-4       5000000           246 ns/op          72 B/op      3 allocs/op
BenchmarkXFmt-4     20000000            57.9 ns/op         0 B/op      0 allocs/op

Details:

https://lab.nexedi.com/kirr/go123/commit/1aa677c8
https://lab.nexedi.com/kirr/go123/blob/c0bbd06e/xfmt/fmt.go

@josharian

This comment has been minimized.

Show comment
Hide comment
@josharian

josharian Apr 20, 2017

Contributor

Note that when the arguments are constants, they no longer allocate on tip, so this is a bit better than it was.

Contributor

josharian commented Apr 20, 2017

Note that when the arguments are constants, they no longer allocate on tip, so this is a bit better than it was.

@navytux

This comment has been minimized.

Show comment
Hide comment
@navytux

navytux Apr 20, 2017

Contributor

@josharian thanks for feedback. For the reference the above benchmark was for tip (go version devel +d728be70f4 Thu Apr 20 01:37:08 2017 +0000 linux/amd64).

Contributor

navytux commented Apr 20, 2017

@josharian thanks for feedback. For the reference the above benchmark was for tip (go version devel +d728be70f4 Thu Apr 20 01:37:08 2017 +0000 linux/amd64).

@bnjjj

This comment has been minimized.

Show comment
Hide comment
@bnjjj

bnjjj Nov 15, 2017

What are the status about this issue ? Is anyone working on ?

bnjjj commented Nov 15, 2017

What are the status about this issue ? Is anyone working on ?

@ianlancetaylor

This comment has been minimized.

Show comment
Hide comment
@ianlancetaylor

ianlancetaylor Nov 15, 2017

Contributor

@bnjjj I'm not aware of anybody actively working on this.

Contributor

ianlancetaylor commented Nov 15, 2017

@bnjjj I'm not aware of anybody actively working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment