github.com/vc42/parquet-go@v0.0.0-20240320194221-1a9adb5f23f5/sparse/gather_test.go (about) 1 package sparse_test 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "math" 7 "testing" 8 "time" 9 "unsafe" 10 11 "github.com/vc42/parquet-go/sparse" 12 ) 13 14 const ( 15 benchmarkGatherPerLoop = 1000 16 ) 17 18 func ExampleGatherUint32() { 19 type point2D struct{ X, Y uint32 } 20 21 buf := make([]point2D, 10) 22 dst := make([]uint32, 10) 23 src := sparse.UnsafeUint32Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 24 25 for i := range buf { 26 buf[i].X = math.MaxUint32 27 buf[i].Y = uint32(2 * i) 28 } 29 30 n := sparse.GatherUint32(dst, src) 31 32 for i, v := range dst[:n] { 33 fmt.Printf("points[%d].Y = %d\n", i, v) 34 } 35 36 // Output: 37 // points[0].Y = 0 38 // points[1].Y = 2 39 // points[2].Y = 4 40 // points[3].Y = 6 41 // points[4].Y = 8 42 // points[5].Y = 10 43 // points[6].Y = 12 44 // points[7].Y = 14 45 // points[8].Y = 16 46 // points[9].Y = 18 47 } 48 49 func ExampleGatherUint64() { 50 type point2D struct{ X, Y uint64 } 51 52 buf := make([]point2D, 10) 53 dst := make([]uint64, 10) 54 src := sparse.UnsafeUint64Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 55 56 for i := range buf { 57 buf[i].X = math.MaxUint64 58 buf[i].Y = uint64(2 * i) 59 } 60 61 n := sparse.GatherUint64(dst, src) 62 63 for i, v := range dst[:n] { 64 fmt.Printf("points[%d].Y = %v\n", i, v) 65 } 66 67 // Output: 68 // points[0].Y = 0 69 // points[1].Y = 2 70 // points[2].Y = 4 71 // points[3].Y = 6 72 // points[4].Y = 8 73 // points[5].Y = 10 74 // points[6].Y = 12 75 // points[7].Y = 14 76 // points[8].Y = 16 77 // points[9].Y = 18 78 } 79 80 func ExampleGatherUint128() { 81 type point2D struct{ X, Y [16]byte } 82 83 buf := make([]point2D, 10) 84 dst := make([][16]byte, 10) 85 src := sparse.UnsafeUint128Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 86 87 for i := range buf { 88 x := uint64(math.MaxUint64) 89 y := uint64(2 * i) 90 binary.LittleEndian.PutUint64(buf[i].X[:], x) 91 binary.LittleEndian.PutUint64(buf[i].Y[:], y) 92 } 93 94 n := sparse.GatherUint128(dst, src) 95 96 for i, v := range dst[:n] { 97 fmt.Printf("points[%d].Y = %v\n", i, binary.LittleEndian.Uint64(v[:])) 98 } 99 100 // Output: 101 // points[0].Y = 0 102 // points[1].Y = 2 103 // points[2].Y = 4 104 // points[3].Y = 6 105 // points[4].Y = 8 106 // points[5].Y = 10 107 // points[6].Y = 12 108 // points[7].Y = 14 109 // points[8].Y = 16 110 // points[9].Y = 18 111 } 112 113 func TestGatherUint32(t *testing.T) { 114 type point2D struct{ X, Y uint32 } 115 116 const N = 100 117 buf := make([]point2D, N+1) 118 dst := make([]uint32, N) 119 src := sparse.UnsafeUint32Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 120 121 for i := range buf { 122 buf[i].X = math.MaxUint32 123 buf[i].Y = uint32(2 * i) 124 } 125 126 if n := sparse.GatherUint32(dst, src); n != N { 127 t.Errorf("wrong number of values gathered: want=%d got=%d", N, n) 128 } 129 130 for i, v := range dst { 131 if v != uint32(2*i) { 132 t.Errorf("wrong value gathered at index %d: want=%d got=%d", i, 2*i, v) 133 } 134 } 135 } 136 137 func TestGatherUint64(t *testing.T) { 138 type point2D struct{ X, Y uint64 } 139 140 const N = 100 141 buf := make([]point2D, N+1) 142 dst := make([]uint64, N) 143 src := sparse.UnsafeUint64Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 144 145 for i := range buf { 146 buf[i].X = math.MaxUint64 147 buf[i].Y = uint64(2 * i) 148 } 149 150 if n := sparse.GatherUint64(dst, src); n != N { 151 t.Errorf("wrong number of values gathered: want=%d got=%d", N, n) 152 } 153 154 for i, v := range dst { 155 if v != uint64(2*i) { 156 t.Errorf("wrong value gathered at index %d: want=%d got=%d", i, 2*i, v) 157 } 158 } 159 } 160 161 func TestGatherUint128(t *testing.T) { 162 type point2D struct{ X, Y [16]byte } 163 164 const N = 100 165 buf := make([]point2D, N+1) 166 dst := make([][16]byte, N) 167 src := sparse.UnsafeUint128Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 168 169 for i := range buf { 170 x := uint64(math.MaxUint64) 171 y := uint64(2 * i) 172 binary.LittleEndian.PutUint64(buf[i].X[:], x) 173 binary.LittleEndian.PutUint64(buf[i].Y[:], y) 174 } 175 176 if n := sparse.GatherUint128(dst, src); n != N { 177 t.Errorf("wrong number of values gathered: want=%d got=%d", N, n) 178 } 179 180 for i, v := range dst { 181 if y := binary.LittleEndian.Uint64(v[:]); y != uint64(2*i) { 182 t.Errorf("wrong value gathered at index %d: want=%d got=%d", i, 2*i, y) 183 } 184 } 185 } 186 187 func BenchmarkGather32(b *testing.B) { 188 type point2D struct{ X, Y uint32 } 189 190 buf := make([]point2D, benchmarkGatherPerLoop) 191 dst := make([]uint32, benchmarkGatherPerLoop) 192 src := sparse.UnsafeUint32Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 193 194 b.SetBytes(4 * benchmarkGatherPerLoop) 195 benchmarkThroughput(b, "gather", func() int { 196 return sparse.GatherUint32(dst, src) 197 }) 198 } 199 200 func BenchmarkGather64(b *testing.B) { 201 type point2D struct{ X, Y uint64 } 202 203 buf := make([]point2D, benchmarkGatherPerLoop) 204 dst := make([]uint64, benchmarkGatherPerLoop) 205 src := sparse.UnsafeUint64Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 206 207 b.SetBytes(8 * benchmarkGatherPerLoop) 208 benchmarkThroughput(b, "gather", func() int { 209 return sparse.GatherUint64(dst, src) 210 }) 211 } 212 213 func BenchmarkGather128(b *testing.B) { 214 type point2D struct{ X, Y [16]byte } 215 216 buf := make([]point2D, benchmarkGatherPerLoop) 217 dst := make([][16]byte, benchmarkGatherPerLoop) 218 src := sparse.UnsafeUint128Array(unsafe.Pointer(&buf[0].Y), len(buf), unsafe.Sizeof(buf[0])) 219 220 b.SetBytes(16 * benchmarkGatherPerLoop) 221 benchmarkThroughput(b, "gather", func() int { 222 return sparse.GatherUint128(dst, src) 223 }) 224 } 225 226 func benchmarkThroughput(b *testing.B, m string, f func() int) { 227 start := time.Now() 228 count := 0 229 230 for i := 0; i < b.N; i++ { 231 count += f() 232 } 233 234 seconds := time.Since(start).Seconds() 235 b.ReportMetric(float64(count)/seconds, m+"/s") 236 }