Commit b71ed4ed authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Robert Griesemer

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: default avatarRobert Griesemer <gri@golang.org>
parent d3434782
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment