113 lines
2.6 KiB
Go
113 lines
2.6 KiB
Go
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)
|
|
}
|
|
}
|