summaryrefslogtreecommitdiff
path: root/src/fmt
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2014-09-22 11:58:15 -0700
committerRob Pike <r@golang.org>2014-09-22 11:58:15 -0700
commit91344febc1f555247b483dfb830c8868aa0be52b (patch)
tree99bb52d291f3084ae889cf056762a6e251aae3dd /src/fmt
parentedc8f73c2071f951fa1fb57a892e9baeb3707426 (diff)
downloadgo-91344febc1f555247b483dfb830c8868aa0be52b.tar.gz
fmt: make printing of ints 25-35% faster
Inspired by a remark by Leonard Holz, use constants for division BenchmarkSprintfEmpty 130 132 +1.54% BenchmarkSprintfString 438 437 -0.23% BenchmarkSprintfInt 417 414 -0.72% BenchmarkSprintfIntInt 663 691 +4.22% BenchmarkSprintfPrefixedInt 791 774 -2.15% BenchmarkSprintfFloat 701 686 -2.14% BenchmarkManyArgs 2584 2469 -4.45% BenchmarkFprintInt 488 357 -26.84% BenchmarkFprintIntNoAlloc 402 265 -34.08% BenchmarkScanInts 1244346 1267574 +1.87% BenchmarkScanRecursiveInt 1748741 1724138 -1.41% Update issue 3463 LGTM=josharian, rsc R=golang-codereviews, josharian, rsc CC=golang-codereviews https://codereview.appspot.com/144250043
Diffstat (limited to 'src/fmt')
-rw-r--r--src/fmt/fmt_test.go17
-rw-r--r--src/fmt/format.go34
2 files changed, 47 insertions, 4 deletions
diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go
index a212c9f70..cca0a495f 100644
--- a/src/fmt/fmt_test.go
+++ b/src/fmt/fmt_test.go
@@ -854,6 +854,23 @@ func BenchmarkManyArgs(b *testing.B) {
})
}
+func BenchmarkFprintInt(b *testing.B) {
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, 123456)
+ }
+}
+
+func BenchmarkFprintIntNoAlloc(b *testing.B) {
+ var x interface{} = 123456
+ var buf bytes.Buffer
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ Fprint(&buf, x)
+ }
+}
+
var mallocBuf bytes.Buffer
var mallocPointer *int // A pointer so we know the interface value won't allocate.
diff --git a/src/fmt/format.go b/src/fmt/format.go
index 8aeffd7b2..255167c8f 100644
--- a/src/fmt/format.go
+++ b/src/fmt/format.go
@@ -199,10 +199,36 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// block but it's not worth the duplication, so ua has 64 bits.
i := len(buf)
ua := uint64(a)
- for ua >= base {
- i--
- buf[i] = digits[ua%base]
- ua /= base
+ // use constants for the division and modulo for more efficient code.
+ // switch cases ordered by popularity.
+ switch base {
+ case 10:
+ for ua >= 10 {
+ i--
+ next := ua / 10
+ buf[i] = byte('0' + ua - next*10)
+ ua = next
+ }
+ case 16:
+ for ua >= 16 {
+ i--
+ buf[i] = digits[ua&0xF]
+ ua >>= 4
+ }
+ case 8:
+ for ua >= 8 {
+ i--
+ buf[i] = byte('0' + ua&7)
+ ua >>= 3
+ }
+ case 2:
+ for ua >= 2 {
+ i--
+ buf[i] = byte('0' + ua&1)
+ ua >>= 1
+ }
+ default:
+ panic("fmt: unknown base; can't happen")
}
i--
buf[i] = digits[ua]