mirror of
https://github.com/golang/go
synced 2024-11-25 10:47:56 -07:00
fmt: replace channel cache with slice.
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
This commit is contained in:
parent
1a13f9b810
commit
12ad9b4315
@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
"unicode"
|
"unicode"
|
||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
@ -78,34 +79,37 @@ type pp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A cache holds a set of reusable objects.
|
// 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.
|
// If more are needed, the cache creates them by calling new.
|
||||||
type cache struct {
|
type cache struct {
|
||||||
saved chan interface{}
|
mu sync.Mutex
|
||||||
|
saved []interface{}
|
||||||
new func() interface{}
|
new func() interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) put(x interface{}) {
|
func (c *cache) put(x interface{}) {
|
||||||
select {
|
c.mu.Lock()
|
||||||
case c.saved <- x:
|
if len(c.saved) < cap(c.saved) {
|
||||||
// saved in cache
|
c.saved = append(c.saved, x)
|
||||||
default:
|
|
||||||
// discard
|
|
||||||
}
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cache) get() interface{} {
|
func (c *cache) get() interface{} {
|
||||||
select {
|
c.mu.Lock()
|
||||||
case x := <-c.saved:
|
n := len(c.saved)
|
||||||
return x // reused from cache
|
if n == 0 {
|
||||||
default:
|
c.mu.Unlock()
|
||||||
return c.new()
|
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 {
|
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) })
|
var ppFree = newCache(func() interface{} { return new(pp) })
|
||||||
|
Loading…
Reference in New Issue
Block a user