optimize AtomicError (#82)

This commit optimize AtomicError using atomic.Value. Benchmarks:

name               old time/op  new time/op  delta
AtomicError/Load-6   305ns ±11%    12ns ± 6%  -96.18%  (p=0.000 n=10+10)
AtomicError/Set-6   314ns ±16%    14ns ± 2%  -95.61%  (p=0.000 n=10+9)
master
Changkun Ou 4 years ago committed by GitHub
parent eccfaba614
commit 762af9dda2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,21 +1,18 @@
package errorx package errorx
import "sync" import "sync/atomic"
type AtomicError struct { type AtomicError struct {
err error err atomic.Value // error
lock sync.Mutex
} }
func (ae *AtomicError) Set(err error) { func (ae *AtomicError) Set(err error) {
ae.lock.Lock() ae.err.Store(err)
ae.err = err
ae.lock.Unlock()
} }
func (ae *AtomicError) Load() error { func (ae *AtomicError) Load() error {
ae.lock.Lock() if v := ae.err.Load(); v != nil {
err := ae.err return v.(error)
ae.lock.Unlock() }
return err return nil
} }

@ -2,6 +2,8 @@ package errorx
import ( import (
"errors" "errors"
"sync"
"sync/atomic"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -19,3 +21,53 @@ func TestAtomicErrorNil(t *testing.T) {
var err AtomicError var err AtomicError
assert.Nil(t, err.Load()) assert.Nil(t, err.Load())
} }
func BenchmarkAtomicError(b *testing.B) {
var aerr AtomicError
wg := sync.WaitGroup{}
b.Run("Load", func(b *testing.B) {
var done uint32
go func() {
for {
if atomic.LoadUint32(&done) != 0 {
break
}
wg.Add(1)
go func() {
aerr.Set(errDummy)
wg.Done()
}()
}
}()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = aerr.Load()
}
b.StopTimer()
atomic.StoreUint32(&done, 1)
wg.Wait()
})
b.Run("Set", func(b *testing.B) {
var done uint32
go func() {
for {
if atomic.LoadUint32(&done) != 0 {
break
}
wg.Add(1)
go func() {
_ = aerr.Load()
wg.Done()
}()
}
}()
b.ResetTimer()
for i := 0; i < b.N; i++ {
aerr.Set(errDummy)
}
b.StopTimer()
atomic.StoreUint32(&done, 1)
wg.Wait()
})
}

Loading…
Cancel
Save