rlp: use atomic.Value for type cache (#22902)
All encoding/decoding operations read the type cache to find the writer/decoder function responsible for a type. When analyzing CPU profiles of geth during sync, I found that the use of sync.RWMutex in cache lookups appears in the profiles. It seems we are running into CPU cache contention problems when package rlp is heavily used on all CPU cores during sync. This change makes it use atomic.Value + a writer lock instead of sync.RWMutex. In the common case where the typeinfo entry is present in the cache, we simply fetch the map and lookup the type.
This commit is contained in:
@ -23,6 +23,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@ -480,3 +481,35 @@ func BenchmarkEncodeBigInts(b *testing.B) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeConcurrentInterface(b *testing.B) {
|
||||
type struct1 struct {
|
||||
A string
|
||||
B *big.Int
|
||||
C [20]byte
|
||||
}
|
||||
value := []interface{}{
|
||||
uint(999),
|
||||
&struct1{A: "hello", B: big.NewInt(0xFFFFFFFF)},
|
||||
[10]byte{1, 2, 3, 4, 5, 6},
|
||||
[]string{"yeah", "yeah", "yeah"},
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for cpu := 0; cpu < runtime.NumCPU(); cpu++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
var buffer bytes.Buffer
|
||||
for i := 0; i < b.N; i++ {
|
||||
buffer.Reset()
|
||||
err := Encode(&buffer, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
Reference in New Issue
Block a user