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

space optimization possible? struct{} takes up space when it is listed last in a struct #17450

Closed
glycerine opened this issue Oct 15, 2016 · 3 comments

Comments

@glycerine
Copy link

I have a use case where it would be useful to have a field inside of a struct that gets changed in type from something to type struct{} -- and then no longer takes up space (I want to use golang structs like protobuf message definitions).

When I checked my assumption however, I find a surprise: when the struct{} field is alone, it doesn't take up any space, as expected. But when the struct{} field is with another member, then it takes up 8 bytes. Ouch! It seems like an opportunity for optimization has been missed.

package main

// run on : go version go1.7 darwin/amd64  (osx 10.11.6)

import (
    "fmt"
    "unsafe"
)

// A is size 0
type A struct {
    NotAMystery struct{} // takes up 0 bytes, as expected
}

// B is size 8
type B struct {
    Hithere int64 // takes up 8 bytes, as expected.
}

// C is size 16
type C struct {
    Hithere int64
    Mystery struct{} // takes up 8 bytes, HUH??
}

func main() {
    var a A
    var b B
    var c C
    fmt.Printf("size of A is '%v'\n", unsafe.Sizeof(a))
    fmt.Printf("size of B is '%v'\n", unsafe.Sizeof(b))
    fmt.Printf("size of C is '%v'\n", unsafe.Sizeof(c))
}

/*output

$ go run meas.go
size of A is '0'
size of B is '8'
size of C is '16'

*/
@glycerine
Copy link
Author

So strange... if I move the struct{} field to the top, it again no longer takes up space!

// D is size 8                                                                                                              
type D struct {
        MoreMystery struct{} // takes up 0 bytes, now that it is at top.                                                    
        Hithere     int64
}

func main() {
        var a A
        var b B
        var c C
        var d D

        fmt.Printf("size of A is '%v'\n", unsafe.Sizeof(a))
        fmt.Printf("size of B is '%v'\n", unsafe.Sizeof(b))
        fmt.Printf("size of C is '%v'\n", unsafe.Sizeof(c))
        fmt.Printf("size of D is '%v'\n", unsafe.Sizeof(d))
}

/*output                                                                                                                    

$ go run meas.go                                                                                                            
size of A is '0'                                                                                                            
size of B is '8'                                                                                                            
size of C is '16'                                                                                                           
size of D is '8'                                                                                                            

*/

@glycerine glycerine changed the title space optimization possible? struct{} takes up space when it is not the only member in a struct space optimization possible? struct{} takes up space when it is listed as 2nd member in a struct Oct 15, 2016
@glycerine glycerine changed the title space optimization possible? struct{} takes up space when it is listed as 2nd member in a struct space optimization possible? struct{} takes up space when it is listed last in a struct Oct 15, 2016
@glycerine
Copy link
Author

The space loss seems happen only when the struct{} is the very last member of the struct.

// G is size 16                                                                                                             
type G struct {
        Starter int64
        Dep6    struct{} // takes up 0                                                                                      
        Hithere int64
}

// H is size 24                                                                                                             
type H struct {
        Starter int64
        Dep6    struct{} // takes up 0                                                                                      
        Hithere int64
        Dep7    struct{} // takes up 8                                                                                      
}

// I is size 24                                                                                                             
type I struct {
        Starter int64
        Hithere int64
        Dep6    struct{} // takes up 0                                                                                      
        Dep7    struct{} // takes up 8                                                                                      
}

@ianlancetaylor
Copy link
Member

This is due to the fix for #9401.

@golang golang locked and limited conversation to collaborators Oct 15, 2017
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

3 participants