]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: replace channel cache with slice.
authorRob Pike <r@golang.org>
Thu, 29 Sep 2011 18:23:06 +0000 (11:23 -0700)
committerRob Pike <r@golang.org>
Thu, 29 Sep 2011 18:23:06 +0000 (11:23 -0700)
Simpler concept, and it turns a queue into a stack.
Speeds up benchmarks noticeably.

Before:
fmt_test.BenchmarkSprintfEmpty 10000000        282 ns/op
fmt_test.BenchmarkSprintfString  2000000        910 ns/op
fmt_test.BenchmarkSprintfInt  5000000        723 ns/op
fmt_test.BenchmarkSprintfIntInt  1000000       1071 ns/op
fmt_test.BenchmarkSprintfPrefixedInt  1000000       1108 ns/op
fmt_test.BenchmarkScanInts     1000    2239510 ns/op
fmt_test.BenchmarkScanRecursiveInt     1000    2365432 ns/op

After:
fmt_test.BenchmarkSprintfEmpty 10000000        232 ns/op
fmt_test.BenchmarkSprintfString  2000000        837 ns/op
fmt_test.BenchmarkSprintfInt  5000000        590 ns/op
fmt_test.BenchmarkSprintfIntInt  2000000        910 ns/op
fmt_test.BenchmarkSprintfPrefixedInt  2000000        996 ns/op
fmt_test.BenchmarkScanInts     1000    2210715 ns/op
fmt_test.BenchmarkScanRecursiveInt     1000    2367800 ns/op

R=rsc, r
CC=golang-dev
https://golang.org/cl/5151044

src/pkg/fmt/print.go

index 738734908079a4eb6a8f2e5ce406a993b3b0f2da..c993af6664f056225eb876b1c1c95a49d3491724 100644 (file)
@@ -9,6 +9,7 @@ import (
        "io"
        "os"
        "reflect"
+       "sync"
        "unicode"
        "utf8"
 )
@@ -78,34 +79,37 @@ type pp struct {
 }
 
 // A cache holds a set of reusable objects.
-// The buffered channel holds the currently available objects.
+// The slice is a stack (LIFO).
 // If more are needed, the cache creates them by calling new.
 type cache struct {
-       saved chan interface{}
+       mu    sync.Mutex
+       saved []interface{}
        new   func() interface{}
 }
 
 func (c *cache) put(x interface{}) {
-       select {
-       case c.saved <- x:
-               // saved in cache
-       default:
-               // discard
+       c.mu.Lock()
+       if len(c.saved) < cap(c.saved) {
+               c.saved = append(c.saved, x)
        }
+       c.mu.Unlock()
 }
 
 func (c *cache) get() interface{} {
-       select {
-       case x := <-c.saved:
-               return x // reused from cache
-       default:
+       c.mu.Lock()
+       n := len(c.saved)
+       if n == 0 {
+               c.mu.Unlock()
                return c.new()
        }
-       panic("not reached")
+       x := c.saved[n-1]
+       c.saved = c.saved[0 : n-1]
+       c.mu.Unlock()
+       return x
 }
 
 func newCache(f func() interface{}) *cache {
-       return &cache{make(chan interface{}, 100), f}
+       return &cache{saved: make([]interface{}, 0, 100), new: f}
 }
 
 var ppFree = newCache(func() interface{} { return new(pp) })