github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/internal/encoder/sort_test.go (about) 1 /* 2 * Copyright 2021 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package encoder 18 19 import ( 20 `bytes` 21 `math/rand` 22 `reflect` 23 `sort` 24 `strconv` 25 `testing` 26 `unsafe` 27 ) 28 29 var keyLen = 15 30 31 type encodedKeyValues []encodedKV 32 type encodedKV struct { 33 key string 34 _MapPair []byte 35 } 36 37 func (sv encodedKeyValues) Len() int { return len(sv) } 38 func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] } 39 func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key } 40 41 func getKvs(std bool) interface{} { 42 var map_size = 1000 43 if std { 44 kvs := make(encodedKeyValues, map_size) 45 for i:=map_size-1; i>=0; i-- { 46 kvs[i] = encodedKV{ 47 key: "\"test_" + strconv.Itoa(i) + "\"", 48 } 49 } 50 return kvs 51 } else { 52 kvs := make([]_MapPair, map_size) 53 for i:=map_size-1; i>=0; i-- { 54 kvs[i] = _MapPair{ 55 k: "\"test_" + strconv.Itoa(i) + "\"", 56 } 57 } 58 return kvs 59 } 60 } 61 62 func BenchmarkSort_Sonic(b *testing.B) { 63 ori := getKvs(false).([]_MapPair) 64 kvs := make([]_MapPair, len(ori)) 65 b.ResetTimer() 66 for i:=0; i<b.N; i++ { 67 copy(kvs, ori) 68 radixQsort(kvs, 0, maxDepth(len(kvs))) 69 } 70 } 71 72 func BenchmarkSort_Std(b *testing.B) { 73 ori := getKvs(true).(encodedKeyValues) 74 kvs := make(encodedKeyValues, len(ori)) 75 b.ResetTimer() 76 for i:=0; i<b.N; i++ { 77 copy(kvs, ori) 78 sort.Sort(kvs) 79 } 80 } 81 82 func BenchmarkSort_Parallel_Sonic(b *testing.B) { 83 ori := getKvs(false).([]_MapPair) 84 b.ResetTimer() 85 b.RunParallel(func(p *testing.PB) { 86 kvs := make([]_MapPair, len(ori)) 87 for p.Next() { 88 copy(kvs, ori) 89 radixQsort(kvs, 0, maxDepth(len(kvs))) 90 } 91 }) 92 } 93 94 func BenchmarkSort_Parallel_Std(b *testing.B) { 95 ori := getKvs(true).(encodedKeyValues) 96 b.ResetTimer() 97 b.RunParallel(func(p *testing.PB) { 98 kvs := make(encodedKeyValues, len(ori)) 99 for p.Next() { 100 copy(kvs, ori) 101 sort.Sort(kvs) 102 } 103 }) 104 } 105 106 type kvSlice []_MapPair 107 108 // Make kvSlice meet sort.Interface. 109 func (self kvSlice) Less(i, j int) bool { return self[i].k < self[j].k } 110 func (self kvSlice) Swap(i, j int) { self[i], self[j] = self[j], self[i] } 111 func (self kvSlice) Len() int { return len(self) } 112 113 //go:nosplit 114 func (self kvSlice) Sort() { 115 radixQsort(self, 0, maxDepth(len(self))) 116 } 117 118 func (self kvSlice) String() string { 119 buf := bytes.NewBuffer(nil) 120 for i, kv := range self { 121 if i > 0 { 122 buf.WriteByte(',') 123 } 124 buf.WriteString(kv.k) 125 } 126 return buf.String() 127 } 128 129 func TestSort_SortRandomKeys(t *testing.T) { 130 kvs := getRandKvs(100, keyLen) 131 sorted := make([]_MapPair, len(kvs)) 132 133 copy(sorted, kvs) 134 sort.Sort(kvSlice(sorted)) 135 kvs.Sort() 136 137 got := kvs.String() 138 want := kvSlice(sorted).String() 139 if !reflect.DeepEqual(got, want) { 140 t.Errorf(" got: %v\nwant: %v\n", got, want) 141 } 142 } 143 144 func genKey(kl int) []byte { 145 l := int(rand.Uint32()%uint32(kl) + 2) 146 k := make([]byte, l) 147 k[0], k[l-1] = '"', '"' 148 for i := 1; i < l-1; i++ { 149 k[i] = byte('a' + int(rand.Uint32()%26)) 150 } 151 return k 152 } 153 154 func getRandKvs(kn int, kl int) kvSlice { 155 keys := make(map[string]bool) 156 kvs := make(kvSlice, 0) 157 for len(keys) < kn { 158 k := genKey(kl) 159 keys[string(k)] = true 160 } 161 for k := range keys { 162 var kv _MapPair 163 kv.k = k 164 kv.v = unsafe.Pointer(&k) 165 kvs = append(kvs, kv) 166 } 167 return kvs 168 }