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: possibly unnecessary allocation for interface data #20380

Closed
gobwas opened this issue May 16, 2017 · 2 comments
Closed

cmd/compile: possibly unnecessary allocation for interface data #20380

gobwas opened this issue May 16, 2017 · 2 comments

Comments

@gobwas
Copy link

gobwas commented May 16, 2017

Go version:

$ go version
go version go1.8.1 darwin/amd64

Issue

Say we have this code:

package main

type Fooer interface {
        Foo()
}

// HandleFooer is intended to show that passing interface will not rasie an allocation.
func HandleFooer(f Fooer) {
        // Passing interface Fooer<*Concrete> will not raise an allocation 
        // even if we do some work on f, such as f.(*Concrete).Foo().
}

type Concrete byte

func (c Concrete) Foo() {}

And if we run these benchmarks (with -gcflags="-l"):

package main

import "testing"

func BenchmarkCallFooer(b *testing.B) {
        for i := 0; i < b.N; i++ {
                var c Concrete = 42// Moved to heap.
                Fooer(&c).Foo()
        }
}

func BenchmarkPassFooer(b *testing.B) {
        for i := 0; i < b.N; i++ {
                var c Concrete = 42 // Not moved to heap.
                HandleFooer(Fooer(&c))
        }
}

The output is:

BenchmarkCallFooer-4    100000000               17.6 ns/op             1 B/op          1 allocs/op
BenchmarkPassFooer-4    500000000                2.99 ns/op            0 B/op          0 allocs/op

With -gcflags="-m -m":

./iface_test.go:17: HandleFooer f does not escape
./iface_test.go:22: Fooer(&c) escapes to heap
./iface_test.go:22:     from Fooer(&c).Foo() (receiver in indirect call) at ./iface_test.go:22
./iface_test.go:22: &c escapes to heap
./iface_test.go:22:     from Fooer(&c) (interface-converted) at ./iface_test.go:22
./iface_test.go:22:     from Fooer(&c).Foo() (receiver in indirect call) at ./iface_test.go:22
./iface_test.go:21: moved to heap: c

Expected behavior: &c stays on stack in both cases.

@bradfitz bradfitz added this to the Go1.10 milestone May 16, 2017
@bradfitz
Copy link
Contributor

/cc @dr2chase

@randall77
Copy link
Contributor

This is a limitation of our current escape analysis. It totally gives up on interface method invocations. We could fix this problem by propagating known concrete types of interface values during escape analysis & doing the method devirtualization.

This limitation has been around for a while.

See #19361
This is basically a simpler form of #14018, I'm going to close as a dup.

@golang golang locked and limited conversation to collaborators May 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants