package main import ( "testing" "unsafe" ) // Большая структура для теста type BigStruct struct { A, B, C, D, E, F, G, H, I, J float64 } // Обычные функции для слайсов структур func ToPtrsStruct(s []BigStruct) []*BigStruct { res := make([]*BigStruct, len(s)) for i := range s { res[i] = &s[i] } return res } func DerefSliceStruct(s []*BigStruct) []BigStruct { res := make([]BigStruct, len(s)) for i := range s { if s[i] != nil { res[i] = *s[i] } } return res } // Unsafe версии func ToPtrsStructUnsafe(s []BigStruct) []*BigStruct { n := len(s) res := make([]*BigStruct, n) if n == 0 { return res } base := unsafe.Pointer(&s[0]) size := unsafe.Sizeof(s[0]) for i := 0; i < n; i++ { res[i] = (*BigStruct)(unsafe.Pointer(uintptr(base) + uintptr(i)*size)) } return res } func DerefSliceStructUnsafe(s []*BigStruct) []BigStruct { n := len(s) res := make([]BigStruct, n) if n == 0 { return res } baseDst := unsafe.Pointer(&res[0]) size := unsafe.Sizeof(res[0]) for i := 0; i < n; i++ { src := unsafe.Pointer(s[i]) dst := unsafe.Pointer(uintptr(baseDst) + uintptr(i)*size) *(*BigStruct)(dst) = *(*BigStruct)(src) } return res } // === Бенчмарки === func BenchmarkToPtrsStruct(b *testing.B) { data := make([]BigStruct, 1_000_000) for i := range data { data[i] = BigStruct{float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i)} } b.ResetTimer() for i := 0; i < b.N; i++ { _ = ToPtrsStruct(data) } } func BenchmarkToPtrsStructUnsafe(b *testing.B) { data := make([]BigStruct, 1_000_000) for i := range data { data[i] = BigStruct{float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i)} } b.ResetTimer() for i := 0; i < b.N; i++ { _ = ToPtrsStructUnsafe(data) } } func BenchmarkDerefSliceStruct(b *testing.B) { data := make([]BigStruct, 1_000_000) for i := range data { data[i] = BigStruct{float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i)} } ptrs := ToPtrsStruct(data) b.ResetTimer() for i := 0; i < b.N; i++ { _ = DerefSliceStruct(ptrs) } } func BenchmarkDerefSliceStructUnsafe(b *testing.B) { data := make([]BigStruct, 1_000_000) for i := range data { data[i] = BigStruct{float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i), float64(i)} } ptrs := ToPtrsStruct(data) b.ResetTimer() for i := 0; i < b.N; i++ { _ = DerefSliceStructUnsafe(ptrs) } }