github.com/parquet-go/parquet-go@v0.21.1-0.20240501160520-b3c3a0c3ed6f/sparse/gather_test.go (about)

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