From 1c1af09b17a5eb9e707ddaf5d5bf8d76e0304e77 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Thu, 13 Apr 2023 03:22:32 +0300 Subject: [PATCH] perf: x/tx/signing/textual: remove unnecessary,expensive regex from method (#15808) Co-authored-by: Marko --- x/tx/signing/textual/bench_test.go | 63 ++++++++++++++++++++++++++++-- x/tx/signing/textual/message.go | 8 ++-- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/x/tx/signing/textual/bench_test.go b/x/tx/signing/textual/bench_test.go index 0e2c4b7012..d113b39bd3 100644 --- a/x/tx/signing/textual/bench_test.go +++ b/x/tx/signing/textual/bench_test.go @@ -1,11 +1,17 @@ -package textual +package textual_test import ( "bytes" "context" + "encoding/json" + "os" "testing" + "github.com/stretchr/testify/require" "google.golang.org/protobuf/reflect/protoreflect" + + "cosmossdk.io/x/tx/internal/testpb" + "cosmossdk.io/x/tx/signing/textual" ) var intValues = []protoreflect.Value{ @@ -22,7 +28,7 @@ var intValues = []protoreflect.Value{ func BenchmarkIntValueRendererFormat(b *testing.B) { ctx := context.Background() - ivr := new(intValueRenderer) + ivr := textual.NewIntValueRenderer(fieldDescriptorFromName("UINT64")) b.ResetTimer() b.ReportAllocs() @@ -49,7 +55,7 @@ var decimalValues = []protoreflect.Value{ func BenchmarkDecimalValueRendererFormat(b *testing.B) { ctx := context.Background() - dvr := new(decValueRenderer) + dvr := textual.NewDecValueRenderer() b.ResetTimer() b.ReportAllocs() @@ -76,7 +82,7 @@ var byteValues = []protoreflect.Value{ func BenchmarkBytesValueRendererFormat(b *testing.B) { ctx := context.Background() - bvr := new(bytesValueRenderer) + bvr := textual.NewBytesValueRenderer() b.ResetTimer() b.ReportAllocs() @@ -88,3 +94,52 @@ func BenchmarkBytesValueRendererFormat(b *testing.B) { } } } + +var sink any + +func BenchmarkMessageValueRenderer_parseRepeated(b *testing.B) { + ctx := context.Background() + raw, err := os.ReadFile("./internal/testdata/repeated.json") + require.NoError(b, err) + + type rendScreens struct { + rend textual.ValueRenderer + screens []textual.Screen + } + + var rsL []*rendScreens + + var testCases []repeatedJSONTest + err = json.Unmarshal(raw, &testCases) + require.NoError(b, err) + + tr, err := textual.NewSignModeHandler(textual.SignModeOptions{CoinMetadataQuerier: mockCoinMetadataQuerier}) + for _, tc := range testCases { + rend := textual.NewMessageValueRenderer(tr, (&testpb.Qux{}).ProtoReflect().Descriptor()) + require.NoError(b, err) + + screens, err := rend.Format(ctx, protoreflect.ValueOf(tc.Proto.ProtoReflect())) + require.NoError(b, err) + require.Equal(b, tc.Screens, screens) + + rsL = append(rsL, &rendScreens{ + rend: rend, + screens: screens, + }) + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + for _, rs := range rsL { + sink, _ = rs.rend.Parse(ctx, rs.screens) + } + } + + if sink == nil { + b.Fatal("Benchmark did not run!") + } + // Reset the sink for reuse. + sink = nil +} diff --git a/x/tx/signing/textual/message.go b/x/tx/signing/textual/message.go index 9affadba86..83668cd7a2 100644 --- a/x/tx/signing/textual/message.go +++ b/x/tx/signing/textual/message.go @@ -261,11 +261,11 @@ func (mr *messageValueRenderer) Parse(ctx context.Context, screens []Screen) (pr return protoreflect.ValueOfMessage(msg), nil } -func (mr *messageValueRenderer) parseRepeated(ctx context.Context, screens []Screen, l protoreflect.List, vr ValueRenderer) error { - // - headerRegex := *regexp.MustCompile(`(\d+) .+`) - res := headerRegex.FindAllStringSubmatch(screens[0].Content, -1) +// +var headerRegex = regexp.MustCompile(`(\d+) .+`) +func (mr *messageValueRenderer) parseRepeated(ctx context.Context, screens []Screen, l protoreflect.List, vr ValueRenderer) error { + res := headerRegex.FindAllStringSubmatch(screens[0].Content, -1) if res == nil { return errors.New("failed to match ") }