Skip to content

cmd/compile: pack structs containing anonymous fields more tightly #31047

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

Open
josharian opened this issue Mar 26, 2019 · 4 comments
Open

cmd/compile: pack structs containing anonymous fields more tightly #31047

josharian opened this issue Mar 26, 2019 · 4 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Performance
Milestone

Comments

@josharian
Copy link
Contributor

I attempted to refactor some common fields (E) out of a struct (T1), yielding (T2). Unfortunately, this changed the packing of the fields, which makes this refactoring infeasible in this case.

type E struct {
	X int
	B uint8
}

type T1 struct {
	X int
	B uint8
	C uint8
}

type T2 struct {
	E
	C uint8
}

Observe the Offset of C in this code: https://play.golang.com/p/ac5CCIWIlZS

On a first pass, I don't see anything in the spec that forbids T1 and T2 being laid out identically in memory.

@josharian josharian added Performance NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Mar 26, 2019
@tmthrgd
Copy link
Contributor

tmthrgd commented Mar 27, 2019

Would that not break the following?

var t T2
e := &t.E
*e = E{}

@josharian
Copy link
Contributor Author

I don’t follow. Why would it?

@randall77
Copy link
Contributor

Right now E.Size() is 16 (on 64-bit archs). We would need E.Size() to be 9 for this proposal to work.
But an array of E would still need to be strided by 16, so we'd need to introduce the concept of two different kinds of size for each type.

@tmthrgd
Copy link
Contributor

tmthrgd commented Mar 28, 2019

Consider a slightly more involved example:

func main() {
    var t T2
    t.C = 42
    modifyE(&t.E)
    println(t.C)
}

//go:noinline
func modifyE(e *E) {
    *e = E{}
}

modifyE would zero 8/16 bytes and override the C field. Keep in mind that function could exist in a different package or *E could be passed through as an interface.

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jul 13, 2022
@mknyszek mknyszek moved this to Triage Backlog in Go Compiler / Runtime Jul 15, 2022
@seankhliao seankhliao added this to the Unplanned milestone Aug 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. Performance
Projects
Status: Triage Backlog
Development

No branches or pull requests

5 participants