Commit bd043d86 authored by Evan Phoenix's avatar Evan Phoenix Committed by Dmitry Vyukov

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/3430Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
parent b49c3ac2
...@@ -32,6 +32,7 @@ import ( ...@@ -32,6 +32,7 @@ import (
"sort" "sort"
"strconv" "strconv"
"sync" "sync"
"sync/atomic"
) )
// Var is an abstract type for all exported variables. // Var is an abstract type for all exported variables.
...@@ -41,26 +42,19 @@ type Var interface { ...@@ -41,26 +42,19 @@ type Var interface {
// Int is a 64-bit integer variable that satisfies the Var interface. // Int is a 64-bit integer variable that satisfies the Var interface.
type Int struct { type Int struct {
mu sync.RWMutex i int64
i int64
} }
func (v *Int) String() string { func (v *Int) String() string {
v.mu.RLock() return strconv.FormatInt(atomic.LoadInt64(&v.i), 10)
defer v.mu.RUnlock()
return strconv.FormatInt(v.i, 10)
} }
func (v *Int) Add(delta int64) { func (v *Int) Add(delta int64) {
v.mu.Lock() atomic.AddInt64(&v.i, delta)
defer v.mu.Unlock()
v.i += delta
} }
func (v *Int) Set(value int64) { func (v *Int) Set(value int64) {
v.mu.Lock() atomic.StoreInt64(&v.i, value)
defer v.mu.Unlock()
v.i = value
} }
// Float is a 64-bit float variable that satisfies the Var interface. // Float is a 64-bit float variable that satisfies the Var interface.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment