Created
March 1, 2016 02:06
-
-
Save riannucci/4bbf625872d33648ed49 to your computer and use it in GitHub Desktop.
A simple benchmark for the default context implementation vs. a bogus caching one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bench | |
import ( | |
"sync" | |
"testing" | |
"time" | |
"golang.org/x/net/context" | |
) | |
type key int | |
func setupLL(depth int) context.Context { | |
c := context.Background() | |
for i := key(0); int(i) < depth; i++ { | |
c = context.WithValue(c, i, i) | |
} | |
return c | |
} | |
func innerLL(b *testing.B, depth int) { | |
c := setupLL(depth) | |
for i := 0; i < b.N; i++ { | |
if c.Value(key(0)) != key(0) { | |
b.FailNow() | |
} | |
} | |
} | |
type cachingContext struct { | |
inner context.Context | |
mu sync.RWMutex | |
cache map[interface{}]interface{} | |
} | |
func (c *cachingContext) Value(key interface{}) interface{} { | |
c.mu.RLock() | |
if ret, ok := c.cache[key]; ok { | |
c.mu.RUnlock() | |
return ret | |
} | |
c.mu.RUnlock() | |
ret := c.inner.Value(key) | |
c.mu.Lock() | |
if c.cache == nil { | |
c.cache = map[interface{}]interface{}{} | |
} | |
c.cache[key] = ret | |
c.mu.Unlock() | |
return ret | |
} | |
func (c *cachingContext) Deadline() (time.Time, bool) { | |
return c.inner.Deadline() | |
} | |
func (c *cachingContext) Err() error { | |
return c.inner.Err() | |
} | |
func (c *cachingContext) Done() <-chan struct{} { | |
return c.inner.Done() | |
} | |
var _ context.Context = (*cachingContext)(nil) | |
func setupCache(depth int) context.Context { | |
c := context.Background() | |
for i := key(0); int(i) < depth; i++ { | |
c = context.WithValue(c, i, i) | |
} | |
c = &cachingContext{inner: c} | |
return c | |
} | |
func innerCache(b *testing.B, depth int) { | |
c := setupCache(depth) | |
for i := 0; i < b.N; i++ { | |
if c.Value(key(0)) != key(0) { | |
b.FailNow() | |
} | |
} | |
} | |
func BenchmarkContextLL10(b *testing.B) { | |
innerLL(b, 10) | |
} | |
func BenchmarkContextLL100(b *testing.B) { | |
innerLL(b, 100) | |
} | |
func BenchmarkContextLL1000(b *testing.B) { | |
innerLL(b, 1000) | |
} | |
func BenchmarkContextC10(b *testing.B) { | |
innerCache(b, 10) | |
} | |
func BenchmarkContextC100(b *testing.B) { | |
innerCache(b, 100) | |
} | |
func BenchmarkContextC1000(b *testing.B) { | |
innerCache(b, 1000) | |
} | |
func BenchmarkOverLL1000(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
if setupLL(1000).Value(key(0)) != key(0) { | |
b.FailNow() | |
} | |
} | |
} | |
func BenchmarkOverC1000(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
if setupCache(1000).Value(key(0)) != key(0) { | |
b.FailNow() | |
} | |
} | |
} | |
// PASS | |
// BenchmarkContextLL10 10000000 188 ns/op | |
// BenchmarkContextLL100 1000000 1062 ns/op | |
// BenchmarkContextLL1000 200000 9772 ns/op | |
// BenchmarkContextC10 20000000 122 ns/op | |
// BenchmarkContextC100 10000000 122 ns/op | |
// BenchmarkContextC1000 20000000 117 ns/op | |
// BenchmarkOverLL1000 5000 309584 ns/op | |
// BenchmarkOverC1000 5000 314663 ns/op | |
// ok github.com/luci/luci-go/bench 14.805s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment