go.uber.org/yarpc@v1.72.1/peer/hashring32/internal/radixsort32/radixsort_test.go (about)

     1  // Copyright (c) 2022 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package radixsort32
    22  
    23  import (
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  // TestRadixSort tests radix sort correctness
    30  func TestRadixSort(t *testing.T) {
    31  	sorter := makeSorter(16, 100, 15000)
    32  	// short break
    33  	testRadixSortReversedSlice(t, sorter, 10)
    34  	// radix sort with buffers in pool
    35  	testRadixSortReversedSlice(t, sorter, 300)
    36  	// radix sort with dynamically allocated buffers
    37  	testRadixSortReversedSlice(t, sorter, 20000)
    38  }
    39  
    40  // TestOptions tests options and fallbacks
    41  func TestOptions(t *testing.T) {
    42  	sorter := makeSorter(3, 500000, 100)
    43  	assert.Equal(t, uint(8), sorter.radix)
    44  	assert.Equal(t, 100, sorter.maxLength)
    45  	assert.Equal(t, 100, sorter.minLength)
    46  
    47  	sorter2 := makeSorter(3, -50, 100)
    48  	assert.Equal(t, 0, sorter2.minLength)
    49  	assert.Equal(t, 100, sorter2.maxLength)
    50  }
    51  
    52  func testRadixSortReversedSlice(t *testing.T, sorter *RadixSorter32, size int) {
    53  	slice := makeRevertedSlice(size)
    54  	sorter.Sort(slice)
    55  	assert.EqualValues(t, makeSortedSlice(size), slice)
    56  }
    57  
    58  func makeSorter(radix, minLen, maxLen int) *RadixSorter32 {
    59  	sorter := New(
    60  		Radix(radix),
    61  		MinLen(minLen),
    62  		MaxLen(maxLen))
    63  	return sorter
    64  }
    65  
    66  func makeRevertedSlice(size int) []uint32 {
    67  	a := make([]uint32, size)
    68  	for i := size - 1; i >= 0; i-- {
    69  		a[i] = uint32(len(a) - 1 - i)
    70  	}
    71  	return a
    72  }
    73  
    74  func makeSortedSlice(size int) []uint32 {
    75  	a := make([]uint32, size)
    76  	for i := 0; i < len(a); i++ {
    77  		a[i] = uint32(i)
    78  	}
    79  	return a
    80  }
    81  
    82  // Benchmarks
    83  
    84  func BenchmarkSortSize150KCompare(b *testing.B) {
    85  	benchmarkCompareSort(b, 150000)
    86  }
    87  
    88  func BenchmarkSortSize150KRadix4(b *testing.B) {
    89  	benchmarkRadixSort(b, 4, 150000)
    90  }
    91  
    92  func BenchmarkSortSize150KRadix8(b *testing.B) {
    93  	benchmarkRadixSort(b, 8, 150000)
    94  }
    95  
    96  func BenchmarkSortSize150KRadix16(b *testing.B) {
    97  	benchmarkRadixSort(b, 16, 150000)
    98  }
    99  
   100  func BenchmarkSortSize15KCompare(b *testing.B) {
   101  	benchmarkCompareSort(b, 15000)
   102  }
   103  
   104  func BenchmarkSortSize15KRadix4(b *testing.B) {
   105  	benchmarkRadixSort(b, 4, 15000)
   106  }
   107  
   108  func BenchmarkSortSize15KRadix8(b *testing.B) {
   109  	benchmarkRadixSort(b, 8, 15000)
   110  }
   111  
   112  func BenchmarkSortSize15KRadix16(b *testing.B) {
   113  	benchmarkRadixSort(b, 16, 15000)
   114  }
   115  
   116  func BenchmarkSortSize1500Compare(b *testing.B) {
   117  	benchmarkCompareSort(b, 1500)
   118  }
   119  
   120  func BenchmarkSortSize1500Radix4(b *testing.B) {
   121  	benchmarkRadixSort(b, 4, 1500)
   122  }
   123  
   124  func BenchmarkSortSize1500Radix8(b *testing.B) {
   125  	benchmarkRadixSort(b, 8, 1500)
   126  }
   127  
   128  func BenchmarkSortSize15000KRadix16(b *testing.B) {
   129  	benchmarkRadixSort(b, 16, 1500)
   130  }
   131  
   132  const par = 8
   133  
   134  func benchmarkRadixSort(b *testing.B, radix, size int) {
   135  	sorter := makeSorter(radix, 0, size)
   136  	b.SetParallelism(par)
   137  	b.ResetTimer()
   138  
   139  	b.RunParallel(func(pb *testing.PB) {
   140  		for pb.Next() {
   141  			sorter.Sort(makeRevertedSlice(size))
   142  		}
   143  	})
   144  }
   145  
   146  func benchmarkCompareSort(b *testing.B, size int) {
   147  	sorter := makeSorter(8, size, size)
   148  	b.SetParallelism(par)
   149  	b.ResetTimer()
   150  
   151  	b.RunParallel(func(pb *testing.PB) {
   152  		for pb.Next() {
   153  			sorter.Sort(makeRevertedSlice(size))
   154  		}
   155  	})
   156  }