Advantages of Go Struct Memory Layout

What are the advantages of Golang’s struct memory layout compared to JVM-like programming language? Golang’s struct is structured kind of like C/C++/Rust struct, their field are flatten into a single memory region. A nested struct (A struct with other struct as the field), will be flatten into the same region. Whereas, programming language like Java, everything is pointer, so if you have non-primitive data type in your struct (or class), they will automatically become pointer and the data will be located somewhere else, not in the same memory region.

What are the advantages of doing this? I can think of a few reasons such as:

  1. It’s easy to encode/decode binary data into struct, just dump the struct binaries.
  2. Cache locality. Having closer memory region increases cache hit rate. This one tbh I’m not so sure if it matters that much.
  3. Passing struct copies its internal memory by default. This can reduces bugs caused by unintentional modification to the struct.

Are there any other reasons? I feel like those 3 reasons are not that big a deal.

Another reason is memory management and performance.

Every allocation of memory on the heap creates a memory area that needs to be released later. This means additional work for the garbage collector. The fewer allocations a struct needs, the better.

And maybe another reason: If struct nesting was done with pointers, the runtime would have to do a deep copy to preserve „pass by value“ semantics. Otherwise, only the top-level struct would be passed by value, but the nested struct would not. This would create an unfavorable mix of copy by value and copy by reference.

I heard Java also have escape analysis, though. So, not every object is allocated on the heap.

True, but a struct with pointers to other structs is more likely to cause escapes to the heap than a struct that has a flat memory layout with no pointers.

Imagine that a function returns a struct whose embedded struct fields are implemented as pointers. The embedded structs would have to be allocated on the heap because they outlive the function they were created in.

(Talking about escape analysis, here is an introductory article about escape analysis in Go that I published just a few days ago.)

In contrast to this, a struct with a flat memory layout can be returned as a copy in one piece. No escaping to the heap would be necessary.

2 Likes