github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/bench/parseint/bench_test.go (about) 1 package parseint_test 2 3 import ( 4 "reflect" 5 "strconv" 6 "testing" 7 "unsafe" 8 ) 9 10 func BenchmarkStdAtoi(b *testing.B) { 11 var out int 12 for i := 0; i < b.N; i++ { 13 out, _ = strconv.Atoi("14") 14 out, _ = strconv.Atoi("148487491") 15 } 16 _ = out 17 } 18 19 func BenchmarkStdAtoiBool(b *testing.B) { 20 var out int 21 for i := 0; i < b.N; i++ { 22 out, _ = parseAtoiBool("14") 23 out, _ = parseAtoiBool("148487491") 24 } 25 _ = out 26 } 27 28 func BenchmarkStdAtoiNeg(b *testing.B) { 29 var out int 30 for i := 0; i < b.N; i++ { 31 out = parseAtoiNeg("14") 32 out = parseAtoiNeg("148487491") 33 } 34 _ = out 35 } 36 37 func BenchmarkTailPtr(b *testing.B) { 38 var out int 39 for i := 0; i < b.N; i++ { 40 _ = parseTailPtr("14", &out) 41 _ = parseTailPtr("148487491", &out) 42 } 43 _ = out 44 } 45 46 func BenchmarkTail(b *testing.B) { 47 var out int 48 for i := 0; i < b.N; i++ { 49 out, _ = parseTail("14") 50 out, _ = parseTail("148487491") 51 } 52 _ = out 53 } 54 55 func BenchmarkTailNeg(b *testing.B) { 56 var out int 57 for i := 0; i < b.N; i++ { 58 out = parseTailNeg("14") 59 out = parseTailNeg("148487491") 60 } 61 _ = out 62 } 63 64 func BenchmarkJeff1(b *testing.B) { 65 var out int 66 for i := 0; i < b.N; i++ { 67 out = parseJeff1("14") 68 out = parseJeff1("148487491") 69 } 70 _ = out 71 } 72 73 func BenchmarkUnsafe(b *testing.B) { 74 var out int 75 for i := 0; i < b.N; i++ { 76 out = parseUnsafe("14") 77 out = parseUnsafe("148487491") 78 } 79 _ = out 80 } 81 82 func parseAtoiBool(s string) (int, bool) { 83 if len(s) == 0 || len(s) > len("999999999") { 84 return 0, false 85 } 86 n := 0 87 for _, c := range []byte(s) { 88 if c < '0' || c > '9' { 89 return 0, false 90 } 91 n = n*10 + int(c-'0') 92 } 93 return n, true 94 } 95 96 func parseAtoiNeg(s string) int { 97 if len(s) == 0 || len(s) > len("999999999") { 98 return -1 99 } 100 n := 0 101 for _, c := range []byte(s) { 102 if c < '0' || c > '9' { 103 return -1 104 } 105 n = n*10 + int(c-'0') 106 } 107 return n 108 } 109 110 func parseTailPtr(s string, dst *int) bool { 111 if len(s) == 0 || len(s) > len("999999999") { 112 *dst = 0 113 return false 114 } 115 n := 0 116 for i := 0; i < len(s); i++ { 117 d := s[i] - '0' 118 if d > 9 { 119 *dst = 0 120 return false 121 } 122 n = n*10 + int(d) 123 } 124 *dst = n 125 return true 126 } 127 128 func parseTail(s string) (int, bool) { 129 if len(s) == 0 || len(s) > len("999999999") { 130 return 0, false 131 } 132 n := 0 133 for i := 0; i < len(s); i++ { 134 d := s[i] - '0' 135 if d > 9 { 136 return 0, false 137 } 138 n = n*10 + int(d) 139 } 140 return n, true 141 } 142 143 func parseTailNeg(s string) int { 144 if len(s) == 0 || len(s) > len("999999999") { 145 return -1 146 } 147 n := 0 148 for i := 0; i < len(s); i++ { 149 d := s[i] - '0' 150 if d > 9 { 151 return -1 152 } 153 n = n*10 + int(d) 154 } 155 return n 156 } 157 158 var deltasJeff1 [10]int 159 160 func init() { 161 v := 0 162 for i := range deltasJeff1 { 163 deltasJeff1[i] = v 164 v = v*10 + '0' 165 } 166 167 // we do this so that we return -1 when len(s) == 0 168 // skips having to check for the len(s) == 0 condition 169 deltasJeff1[0] = 1 170 } 171 172 func parseJeff1(s string) (n int) { 173 var c byte 174 var i int 175 176 next: 177 if i < len(s) { 178 c = s[i] 179 i = i + 1 180 n = 10*n + int(c) 181 182 if c-'0' > 9 { 183 return -1 184 } 185 goto next 186 } 187 188 if len(s) < len(deltas) { 189 return n - deltas[len(s)] 190 } 191 return -1 192 } 193 194 var deltas [10]int 195 196 func init() { 197 v := 0 198 for i := range deltas { 199 deltas[i] = v 200 v = v*10 + '0' 201 } 202 deltas[0] = 1 203 } 204 205 // because life without unsafe and reflect would be too safe. 206 func parseUnsafe(s string) (n int) { 207 sp := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data) 208 lp := uintptr(sp) + uintptr(len(s)) 209 next: 210 if uintptr(sp) < lp { 211 c := *(*byte)(sp) 212 n = 10*n + int(c) 213 if c-'0' > 9 { 214 return -1 215 } 216 sp = unsafe.Pointer(uintptr(sp) + 1) 217 goto next 218 } 219 if len(s) < len(deltas) { 220 return n - deltas[len(s)] 221 } 222 return -1 223 }