package test

import (
	"runtime"
	"testing"
)

// 测试用的结构体
type Person struct {
	Name    string
	Age     int
	Address string
	Email   string
	Phone   string
	Balance float64
	Active  bool
}

// 返回指针
func NewPersonPtr(name string, age int) *Person {
	return &Person{
		Name:    name,
		Age:     age,
		Address: "Some Address",
		Email:   "test@example.com",
		Phone:   "1234567890",
		Balance: 1000.0,
		Active:  true,
	}
}

// 返回值
func NewPersonValue(name string, age int) Person {
	return Person{
		Name:    name,
		Age:     age,
		Address: "Some Address",
		Email:   "test@example.com",
		Phone:   "1234567890",
		Balance: 1000.0,
		Active:  true,
	}
}

var globalPtr *Person
var globalValue Person

func BenchmarkSmallStruct(b *testing.B) {
	runtime.GC()
	b.Run("ValueWithSmallStruct", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p := NewPersonValue("John", 30)
			globalValue = p
		}
	})

	runtime.Gosched()
	runtime.GC()
	b.Run("PointerWithSmallStruct", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			p := NewPersonPtr("John", 30)
			globalPtr = p
		}
	})
}

var globalLargePtr *LargeStruct
var globalLargeValue LargeStruct

func BenchmarkLargeStruct(b *testing.B) {
	runtime.GC()
	b.Run("ValueWithLargeStruct", func(b *testing.B) {
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			s := NewLargeValue(1)
			globalLargeValue = s
		}
	})

	runtime.Gosched()
	runtime.GC()
	b.Run("PointerWithLargeStruct", func(b *testing.B) {
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			p := NewLargePtr(1)
			globalLargePtr = p
		}
	})
}

func NewLargePtr(id int) *LargeStruct {
	return &LargeStruct{
		ID: id,
	}
}

// 返回值
func NewLargeValue(id int) LargeStruct {
	return LargeStruct{
		ID: id,
	}
}

// Benchmark 大结构体指针
type LargeStruct struct {
	Data [1024]byte
	ID   int
}
