Hi Everyone, https://gist.github.com/rkerno/c875609bdeb2459582609da36b54bf72
I'm struggling to wrap my head around the root cause of this issue. Accessing certain fields of a struct triggers go to allocate the complete struct on the heap. The key ingredients are: - A struct with a contained slice of structs defined inline - Calls to functions via a function pointer What follows is a contrived example to demonstrate / investigate the problem. const ( // // When requireZeroAllocations == true... // // BenchmarkAllocations-2 27763290 52.28 ns/op 0 B/op 0 allocs/op // // When requireZeroAllocations == false... // // BenchmarkAllocations-2 14403922 1532.00 ns/op 2304 B/op 2 allocs/op // requireZeroAllocations = false ) type ( X struct { id uint key string value any children []X useId useIdFunc useX useXFunc useKey useKeyFunc useValue useValueFunc unused [128]uint64 // Demonstrates that the whole struct is placed on the heap! } useIdFunc = func(id uint) useXFunc = func(key string, value any) useKeyFunc = func(key string) useValueFunc = func(value any) ) func scanX(x X) { if len(x.children) > 0 { for i := 0; i < len(x.children); i++ { scanX(x.children[i]) } return } x.useId(x.id) if !requireZeroAllocations { // Why can we access the id field without an allocation, but as soon as we access // the string or any fields the entire struct is placed on the heap? x.useKey(x.key) x.useX(x.key, x.value) x.useValue(x.value) } } func printId(id uint) { } func printX(key string, value any) { } func printKey(key string) { } func printValue(value any) { } The benchmark used to demonstrate the behaviour is: func BenchmarkAllocations(b *testing.B) { b.ReportAllocs() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { scanX( X{ id: 0, key: "root", value: nil, children: []X{ { id: 1, key: "level1", value: nil, children: []X{ { id: 2, key: "k1", value: "v1", children: nil, useId: printId, useX: printX, useKey: printKey, useValue: printValue, }, }, }, }, }, ) } }) } Any insights or ideas why go exhibits this behaviour would be appreciated. Cheers, Rik -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3ff0270c-caf0-4a23-9cdf-08bf40e83a33n%40googlegroups.com.