aboutsummaryrefslogtreecommitdiff
path: root/src/strconv
diff options
context:
space:
mode:
authorMartin Möhrmann <martisch@uos.de>2015-01-06 19:48:31 +0100
committerRobert Griesemer <gri@golang.org>2015-01-08 20:58:26 +0000
commit06ed8f0df76e9b0256de286392d42d1ea7dec809 (patch)
treedaa3419230a2bb46e88dd6bd211ffca14442a12b /src/strconv
parentdb7fd1c1420d5ef2f874f40c0349b35007568c77 (diff)
downloadgo-06ed8f0df76e9b0256de286392d42d1ea7dec809.tar.xz
strconv: speed up atoi for common cases
Add compile time constants for bases 10 and 16 instead of computing the cutoff value on every invocation of ParseUint by a division. Reduce usage of slice operations. amd64: benchmark old ns/op new ns/op delta BenchmarkAtoi 44.6 36.0 -19.28% BenchmarkAtoiNeg 44.2 38.9 -11.99% BenchmarkAtoi64 72.5 56.7 -21.79% BenchmarkAtoi64Neg 66.1 58.6 -11.35% 386: benchmark old ns/op new ns/op delta BenchmarkAtoi 86.6 73.0 -15.70% BenchmarkAtoiNeg 86.6 72.3 -16.51% BenchmarkAtoi64 126 108 -14.29% BenchmarkAtoi64Neg 126 108 -14.29% Change-Id: I0a271132120d776c97bb4ed1099793c73e159893 Reviewed-on: https://go-review.googlesource.com/2460 Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/strconv')
-rw-r--r--src/strconv/atoi.go40
1 files changed, 22 insertions, 18 deletions
diff --git a/src/strconv/atoi.go b/src/strconv/atoi.go
index 9ecec5a58b..965e3a218f 100644
--- a/src/strconv/atoi.go
+++ b/src/strconv/atoi.go
@@ -36,13 +36,7 @@ const intSize = 32 << (^uint(0) >> 63)
// IntSize is the size in bits of an int or uint value.
const IntSize = intSize
-// Return the first number n such that n*base >= 1<<64.
-func cutoff64(base int) uint64 {
- if base < 2 {
- return 0
- }
- return (1<<64-1)/uint64(base) + 1
-}
+const maxUint64 = (1<<64 - 1)
// ParseUint is like ParseInt but for unsigned numbers.
func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
@@ -52,7 +46,7 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
bitSize = int(IntSize)
}
- s0 := s
+ i := 0
switch {
case len(s) < 1:
err = ErrSyntax
@@ -65,14 +59,15 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
// Look for octal, hex prefix.
switch {
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
- base = 16
- s = s[2:]
- if len(s) < 1 {
+ if len(s) < 3 {
err = ErrSyntax
goto Error
}
+ base = 16
+ i = 2
case s[0] == '0':
base = 8
+ i = 1
default:
base = 10
}
@@ -82,11 +77,20 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
goto Error
}
- n = 0
- cutoff = cutoff64(base)
+ // Cutoff is the smallest number such that cutoff*base > maxUint64.
+ // Use compile-time constants for common cases.
+ switch base {
+ case 10:
+ cutoff = maxUint64/10 + 1
+ case 16:
+ cutoff = maxUint64/16 + 1
+ default:
+ cutoff = maxUint64/uint64(base) + 1
+ }
+
maxVal = 1<<uint(bitSize) - 1
- for i := 0; i < len(s); i++ {
+ for ; i < len(s); i++ {
var v byte
d := s[i]
switch {
@@ -101,7 +105,7 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
err = ErrSyntax
goto Error
}
- if int(v) >= base {
+ if v >= byte(base) {
n = 0
err = ErrSyntax
goto Error
@@ -109,7 +113,7 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
if n >= cutoff {
// n*base overflows
- n = 1<<64 - 1
+ n = maxUint64
err = ErrRange
goto Error
}
@@ -118,7 +122,7 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
n1 := n + uint64(v)
if n1 < n || n1 > maxVal {
// n+v overflows
- n = 1<<64 - 1
+ n = maxUint64
err = ErrRange
goto Error
}
@@ -128,7 +132,7 @@ func ParseUint(s string, base int, bitSize int) (n uint64, err error) {
return n, nil
Error:
- return n, &NumError{"ParseUint", s0, err}
+ return n, &NumError{"ParseUint", s, err}
}
// ParseInt interprets a string s in the given base (2 to 36) and