diff options
author | Evan Phoenix <evan@phx.io> | 2015-01-28 09:16:44 -0800 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2015-01-29 08:24:00 +0000 |
commit | bd043d862962ec844994a658d8b4f8ab89b6d80e (patch) | |
tree | 95803d98c48c25f1948638a80c9788e261adfdbc /src/expvar | |
parent | b49c3ac2d50c1aed28bc55b09415ad8d861237e9 (diff) | |
download | go-bd043d862962ec844994a658d8b4f8ab89b6d80e.tar.gz go-bd043d862962ec844994a658d8b4f8ab89b6d80e.zip |
expvar: Use sync/atomic to manipulate Int for better perf
Using a mutex to protect a single int operation is quite heavyweight.
Using sync/atomic provides much better performance. This change was
benchmarked as such:
BenchmarkSync 10000000 139 ns/op
BenchmarkAtomic 200000000 9.90 ns/op
package blah
import (
"sync"
"sync/atomic"
"testing"
)
type Int struct {
mu sync.RWMutex
i int64
}
func (v *Int) Add(delta int64) {
v.mu.Lock()
defer v.mu.Unlock()
v.i += delta
}
type AtomicInt struct {
i int64
}
func (v *AtomicInt) Add(delta int64) {
atomic.AddInt64(&v.i, delta)
}
func BenchmarkSync(b *testing.B) {
s := new(Int)
for i := 0; i < b.N; i++ {
s.Add(1)
}
}
func BenchmarkAtomic(b *testing.B) {
s := new(AtomicInt)
for i := 0; i < b.N; i++ {
s.Add(1)
}
}
Change-Id: I6998239c785967647351bbfe8533c38e4894543b
Reviewed-on: https://go-review.googlesource.com/3430
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Diffstat (limited to 'src/expvar')
-rw-r--r-- | src/expvar/expvar.go | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/src/expvar/expvar.go b/src/expvar/expvar.go index 9b6dab487c..2cb515a678 100644 --- a/src/expvar/expvar.go +++ b/src/expvar/expvar.go @@ -32,6 +32,7 @@ import ( "sort" "strconv" "sync" + "sync/atomic" ) // Var is an abstract type for all exported variables. @@ -41,26 +42,19 @@ type Var interface { // Int is a 64-bit integer variable that satisfies the Var interface. type Int struct { - mu sync.RWMutex - i int64 + i int64 } func (v *Int) String() string { - v.mu.RLock() - defer v.mu.RUnlock() - return strconv.FormatInt(v.i, 10) + return strconv.FormatInt(atomic.LoadInt64(&v.i), 10) } func (v *Int) Add(delta int64) { - v.mu.Lock() - defer v.mu.Unlock() - v.i += delta + atomic.AddInt64(&v.i, delta) } func (v *Int) Set(value int64) { - v.mu.Lock() - defer v.mu.Unlock() - v.i = value + atomic.StoreInt64(&v.i, value) } // Float is a 64-bit float variable that satisfies the Var interface. |