diff --git a/data.go b/data.go index a3d0b26..3979434 100644 --- a/data.go +++ b/data.go @@ -8,6 +8,16 @@ import ( "math" ) +var ( + // zeroValueTriangleData is the default value of a TriangleData element + zeroValueTriangleData = struct { + Position Vec + Color RGBA + Picture Vec + Intensity float64 + }{Color: RGBA{1, 1, 1, 1}} +) + // TrianglesData specifies a list of Triangles vertices with three common properties: // TrianglesPosition, TrianglesColor and TrianglesPicture. type TrianglesData []struct { @@ -22,9 +32,11 @@ type TrianglesData []struct { // Prefer this function to make(TrianglesData, len), because make zeros them, while this function // does the correct intialization. func MakeTrianglesData(len int) *TrianglesData { - td := &TrianglesData{} - td.SetLen(len) - return td + td := make(TrianglesData, len) + for i := 0; i < len; i++ { + td[i] = zeroValueTriangleData + } + return &td } // Len returns the number of vertices in TrianglesData. @@ -38,15 +50,15 @@ func (td *TrianglesData) Len() int { // values ((0, 0), white, (0, 0), 0). func (td *TrianglesData) SetLen(len int) { if len > td.Len() { + newTD := make(TrianglesData, len) + copy(newTD, *td) + needAppend := len - td.Len() - for i := 0; i < needAppend; i++ { - *td = append(*td, struct { - Position Vec - Color RGBA - Picture Vec - Intensity float64 - }{Color: RGBA{1, 1, 1, 1}}) + for i := td.Len(); i < needAppend; i++ { + newTD[i] = zeroValueTriangleData } + + *td = newTD } if len < td.Len() { *td = (*td)[:len] @@ -96,10 +108,9 @@ func (td *TrianglesData) Update(t Triangles) { // Copy returns an exact independent copy of this TrianglesData. func (td *TrianglesData) Copy() Triangles { - copyTd := TrianglesData{} - copyTd.SetLen(td.Len()) + copyTd := MakeTrianglesData(td.Len()) copyTd.Update(td) - return ©Td + return copyTd } // Position returns the position property of i-th vertex. diff --git a/data_test.go b/data_test.go new file mode 100644 index 0000000..7d6d8c3 --- /dev/null +++ b/data_test.go @@ -0,0 +1,244 @@ +package pixel_test + +import ( + "testing" + + "github.com/faiface/pixel" +) + +func BenchmarkTrianglesData_Len(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + }{ + { + name: "Small slice", + tData: pixel.MakeTrianglesData(10), + }, + { + name: "Large slice", + tData: pixel.MakeTrianglesData(10000), + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = tt.tData.Len() + } + }) + } +} + +func BenchmarkTrianglesData_SetLen(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + nextLenFunc func(int, int) (int, int) + }{ + { + name: "Stay same size", + tData: pixel.MakeTrianglesData(50), + nextLenFunc: func(i, j int) (int, int) { return 50, 0 }, + }, + { + name: "Change size", + tData: pixel.MakeTrianglesData(50), + nextLenFunc: func(i, j int) (int, int) { + // 0 is shrink + if j == 0 { + next := i - 1 + if next < 1 { + return 2, 1 + } + return next, 0 + } + + // other than 0 is grow + next := i + 1 + if next == 100 { + return next, 0 + } + return next, 1 + }, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + var newLen int + var c int + for i := 0; i < b.N; i++ { + newLen, c = tt.nextLenFunc(newLen, c) + tt.tData.SetLen(newLen) + } + }) + } +} + +func BenchmarkTrianglesData_Slice(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + }{ + { + name: "Basic slice", + tData: pixel.MakeTrianglesData(100), + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = tt.tData.Slice(25, 50) + } + }) + } +} + +func BenchmarkTrianglesData_Update(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + t pixel.Triangles + }{ + { + name: "Small Triangles", + tData: pixel.MakeTrianglesData(20), + t: pixel.MakeTrianglesData(20), + }, + { + name: "Large Triangles", + tData: pixel.MakeTrianglesData(10000), + t: pixel.MakeTrianglesData(10000), + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + tt.tData.Update(tt.t) + } + }) + } +} + +func BenchmarkTrianglesData_Copy(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + }{ + { + name: "Small copy", + tData: pixel.MakeTrianglesData(20), + }, + { + name: "Large copy", + tData: pixel.MakeTrianglesData(10000), + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = tt.tData.Copy() + } + }) + } +} + +func BenchmarkTrianglesData_Position(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + position int + }{ + { + name: "Getting beginning position", + tData: pixel.MakeTrianglesData(1000), + position: 2, + }, + { + name: "Getting middle position", + tData: pixel.MakeTrianglesData(1000), + position: 500, + }, + { + name: "Getting end position", + tData: pixel.MakeTrianglesData(1000), + position: 999, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = tt.tData.Position(tt.position) + } + }) + } +} + +func BenchmarkTrianglesData_Color(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + position int + }{ + { + name: "Getting beginning position", + tData: pixel.MakeTrianglesData(1000), + position: 2, + }, + { + name: "Getting middle position", + tData: pixel.MakeTrianglesData(1000), + position: 500, + }, + { + name: "Getting end position", + tData: pixel.MakeTrianglesData(1000), + position: 999, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = tt.tData.Color(tt.position) + } + }) + } +} + +func BenchmarkTrianglesData_Picture(b *testing.B) { + tests := []struct { + name string + tData *pixel.TrianglesData + position int + }{ + { + name: "Getting beginning position", + tData: pixel.MakeTrianglesData(1000), + position: 2, + }, + { + name: "Getting middle position", + tData: pixel.MakeTrianglesData(1000), + position: 500, + }, + { + name: "Getting end position", + tData: pixel.MakeTrianglesData(1000), + position: 999, + }, + } + + for _, tt := range tests { + b.Run(tt.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = tt.tData.Picture(tt.position) + } + }) + } +}