benchmark different mutex versions

This commit is contained in:
William Banfield
2021-10-26 09:52:26 +02:00
parent fcebb1e015
commit d39a552c8a
2 changed files with 136 additions and 1 deletions

View File

@@ -160,7 +160,7 @@ func NopMetrics() *Metrics {
// type that is passed in.
// This method uses a map on the Metrics struct so that each label name only needs
// to be produced once to prevent expensive string operations.
func (m *Metrics) ValueToMetricLabel(i interface{}) string {
func (m *Metrics) ValueToMetricLabelRW(i interface{}) string {
t := reflect.TypeOf(i)
m.mtx.RLock()
@@ -178,3 +178,27 @@ func (m *Metrics) ValueToMetricLabel(i interface{}) string {
m.messageLabelNames[t] = l
return l
}
// ValueToMetricLabel is a method that is used to produce a prometheus label value of the golang
// type that is passed in.
// This method uses a map on the Metrics struct so that each label name only needs
// to be produced once to prevent expensive string operations.
func (m *Metrics) ValueToMetricLabelM(i interface{}) string {
t := reflect.TypeOf(i)
m.mtx.Lock()
defer m.mtx.Unlock()
if s, ok := m.messageLabelNames[t]; ok {
return s
}
s := t.String()
ss := valueToLabelRegexp.FindStringSubmatch(s)
l := fmt.Sprintf("%s_%s", ss[1], ss[2])
m.messageLabelNames[t] = l
return l
}
func (m *Metrics) ValueToMetricLabel(i interface{}) string {
return m.ValueToMetricLabelRW(i)
}

View File

@@ -1,9 +1,11 @@
package p2p
import (
"sync"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/proto/tendermint/consensus"
"github.com/tendermint/tendermint/proto/tendermint/p2p"
)
@@ -17,3 +19,112 @@ func TestValueToMetricsLabel(t *testing.T) {
str = m.ValueToMetricLabel(r)
assert.Equal(t, "p2p_PexResponse", str)
}
func BenchmarkValueToMetricsLabel(b *testing.B) {
numGoRoutines := 16
msgTypes := []interface{}{
&p2p.PexResponse{},
&p2p.PexRequest{},
&p2p.PexAddress{},
&consensus.HasVote{},
&consensus.NewRoundStep{},
&consensus.NewValidBlock{},
&consensus.VoteSetBits{},
&consensus.VoteSetMaj23{},
&consensus.Vote{},
&consensus.BlockPart{},
&consensus.ProposalPOL{},
}
b.Run("RW Mutex Version", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
m := NopMetrics()
wg := &sync.WaitGroup{}
b.StartTimer()
for j := 0; j < numGoRoutines; j++ {
wg.Add(1)
go func() {
defer wg.Done()
for k := 0; k < 100; k++ {
m.ValueToMetricLabelRW(msgTypes[k%len(msgTypes)])
}
}()
}
wg.Wait()
}
})
b.Run("Mutex Version", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
m := NopMetrics()
wg := &sync.WaitGroup{}
b.StartTimer()
for j := 0; j < numGoRoutines; j++ {
wg.Add(1)
go func() {
defer wg.Done()
for k := 0; k < 100; k++ {
m.ValueToMetricLabelM(msgTypes[k%len(msgTypes)])
}
}()
}
wg.Wait()
}
})
}
func BenchmarkValueToMetricsLabelPrefilled(b *testing.B) {
numGoRoutines := 16
msgTypes := []interface{}{
&p2p.PexResponse{},
&p2p.PexRequest{},
&p2p.PexAddress{},
&consensus.HasVote{},
&consensus.NewRoundStep{},
&consensus.NewValidBlock{},
&consensus.VoteSetBits{},
&consensus.VoteSetMaj23{},
&consensus.Vote{},
&consensus.BlockPart{},
&consensus.ProposalPOL{},
}
// create a metric set and put all of the types into the label map.
m := NopMetrics()
for _, t := range msgTypes {
m.ValueToMetricLabel(t)
}
b.Run("RW Mutex Version", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
wg := &sync.WaitGroup{}
b.StartTimer()
for j := 0; j < numGoRoutines; j++ {
wg.Add(1)
go func() {
defer wg.Done()
for k := 0; k < 100; k++ {
m.ValueToMetricLabelRW(msgTypes[k%len(msgTypes)])
}
}()
}
wg.Wait()
}
})
b.Run("Mutex Version", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
wg := &sync.WaitGroup{}
b.StartTimer()
for j := 0; j < numGoRoutines; j++ {
wg.Add(1)
go func() {
defer wg.Done()
for k := 0; k < 100; k++ {
m.ValueToMetricLabelM(msgTypes[k%len(msgTypes)])
}
}()
}
wg.Wait()
}
})
}