aboutsummaryrefslogtreecommitdiff
path: root/src/strconv
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2017-03-11 08:48:56 +0100
committerRobert Griesemer <gri@golang.org>2017-03-12 21:37:32 +0000
commitb71ed4edc6a5663caac434f9c2bea47dbc37db15 (patch)
tree0714fabf7b55cf3930178178e62887b5cbc12f50 /src/strconv
parentd343478295f8635e60014fa9481ccea04b6c53a8 (diff)
downloadgo-b71ed4edc6a5663caac434f9c2bea47dbc37db15.tar.xz
strconv: fix performance regression in integer formatting on 32bit platforms
Some of the changes in CL golang.org/cl/38071/ assumed that / and % could always be combined to use only one DIV instruction. However, this is not the case for 64bit operands on a 32bit platform which use seperate runtime functions to calculate division and modulo. This CL restores the original optimizations that help on 32bit platforms with negligible impact on 64bit platforms. 386: name old time/op new time/op delta FormatInt-2 6.06µs ± 0% 6.02µs ± 0% -0.70% (p=0.000 n=20+20) AppendInt-2 4.98µs ± 0% 4.98µs ± 0% ~ (p=0.747 n=18+18) FormatUint-2 1.93µs ± 0% 1.85µs ± 0% -4.19% (p=0.000 n=20+20) AppendUint-2 1.71µs ± 0% 1.64µs ± 0% -3.68% (p=0.000 n=20+20) amd64: name old time/op new time/op delta FormatInt-2 2.41µs ± 0% 2.41µs ± 0% -0.09% (p=0.010 n=18+18) AppendInt-2 1.77µs ± 0% 1.77µs ± 0% +0.08% (p=0.000 n=18+18) FormatUint-2 653ns ± 1% 653ns ± 0% ~ (p=0.178 n=20+20) AppendUint-2 514ns ± 0% 513ns ± 0% -0.13% (p=0.000 n=20+17) Change-Id: I574a18e54fb41b25fbe51ce696e7a8765abc79a6 Reviewed-on: https://go-review.googlesource.com/38051 Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/strconv')
-rw-r--r--src/strconv/itoa.go21
1 files changed, 12 insertions, 9 deletions
diff --git a/src/strconv/itoa.go b/src/strconv/itoa.go
index 0cbbf06594..d0b4258d76 100644
--- a/src/strconv/itoa.go
+++ b/src/strconv/itoa.go
@@ -80,11 +80,11 @@ func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s
if host32bit {
// convert the lower digits using 32bit operations
for u >= 1e9 {
- // the compiler recognizes q = a/b; r = a%b
- // and produces only one DIV instruction;
- // no need to be clever here
+ // Avoid using r = a%b in addition to q = a/b
+ // since 64bit division and modulo operations
+ // are calculated by runtime functions on 32bit machines.
q := u / 1e9
- us := uint(u % 1e9) // u % 1e9 fits into a uint
+ us := uint(u - q*1e9) // u % 1e9 fits into a uint
for j := 9; j > 0; j-- {
i--
a[i] = byte(us%10 + '0')
@@ -117,19 +117,22 @@ func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s
}
// u < base
i--
- a[i] = digits[u]
-
+ a[i] = digits[uint(u)]
} else {
// general case
b := uint64(base)
for u >= b {
i--
- a[i] = digits[u%b]
- u /= b
+ // Avoid using r = a%b in addition to q = a/b
+ // since 64bit division and modulo operations
+ // are calculated by runtime functions on 32bit machines.
+ q := u / b
+ a[i] = digits[uint(u-q*b)]
+ u = q
}
// u < base
i--
- a[i] = digits[u]
+ a[i] = digits[uint(u)]
}
// add sign, if any