From 4ab18d084a15bf4da9537ea8f4031d3bc1e50d11 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Wed, 20 Oct 2021 14:32:01 +0300 Subject: [PATCH] rpc/request: add unmarshal benchmark Signed-off-by: Evgeniy Stratonikov --- pkg/rpc/request/types_test.go | 49 ++++++++++++++++++++++++++++ pkg/rpc/server/server_helper_test.go | 6 ++-- pkg/rpc/server/server_test.go | 45 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 pkg/rpc/request/types_test.go diff --git a/pkg/rpc/request/types_test.go b/pkg/rpc/request/types_test.go new file mode 100644 index 000000000..aabbb27fe --- /dev/null +++ b/pkg/rpc/request/types_test.go @@ -0,0 +1,49 @@ +package request + +import ( + "bytes" + "encoding/json" + "io" + "testing" +) + +type readCloser struct { + io.Reader +} + +func (readCloser) Close() error { return nil } + +func BenchmarkUnmarshal(b *testing.B) { + req := []byte(`{"jsonrpc":"2.0", "method":"invokefunction","params":["0x50befd26fdf6e4d957c11e078b24ebce6291456f", "someMethod", [{"type": "String", "value": "50befd26fdf6e4d957c11e078b24ebce6291456f"}, {"type": "Integer", "value": "42"}, {"type": "Boolean", "value": false}]]}`) + b.Run("single", func(b *testing.B) { + b.ReportAllocs() + b.Run("unmarshal", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + in := new(In) + b.StartTimer() + err := json.Unmarshal(req, in) + if err != nil { + b.FailNow() + } + } + }) + b.Run("decode data", func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + r := NewRequest() + r.In = new(In) + rd := bytes.NewReader(req) + b.StartTimer() + err := r.DecodeData(readCloser{rd}) + if err != nil { + b.FailNow() + } + } + }) + }) +} diff --git a/pkg/rpc/server/server_helper_test.go b/pkg/rpc/server/server_helper_test.go index 24c18da73..6dbb23608 100644 --- a/pkg/rpc/server/server_helper_test.go +++ b/pkg/rpc/server/server_helper_test.go @@ -28,7 +28,7 @@ const ( notaryPass = "one" ) -func getUnitTestChain(t *testing.T, enableOracle bool, enableNotary bool) (*core.Blockchain, *oracle.Oracle, config.Config, *zap.Logger) { +func getUnitTestChain(t testing.TB, enableOracle bool, enableNotary bool) (*core.Blockchain, *oracle.Oracle, config.Config, *zap.Logger) { net := netmode.UnitTestNet configPath := "../../../config" cfg, err := config.Load(configPath, net) @@ -97,7 +97,7 @@ func getTestBlocks(t *testing.T) []*block.Block { return blocks } -func initClearServerWithServices(t *testing.T, needOracle bool, needNotary bool) (*core.Blockchain, *Server, *httptest.Server) { +func initClearServerWithServices(t testing.TB, needOracle bool, needNotary bool) (*core.Blockchain, *Server, *httptest.Server) { chain, orc, cfg, logger := getUnitTestChain(t, needOracle, needNotary) serverConfig := network.NewServerConfig(cfg) @@ -113,7 +113,7 @@ func initClearServerWithServices(t *testing.T, needOracle bool, needNotary bool) return chain, &rpcServer, srv } -func initClearServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *httptest.Server) { +func initClearServerWithInMemoryChain(t testing.TB) (*core.Blockchain, *Server, *httptest.Server) { return initClearServerWithServices(t, false, false) } diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index c0fca9a7b..cd640ca35 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -27,7 +27,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/network" "github.com/nspcc-dev/neo-go/pkg/network/payload" + "github.com/nspcc-dev/neo-go/pkg/rpc/request" "github.com/nspcc-dev/neo-go/pkg/rpc/response" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" rpc2 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster" @@ -39,6 +41,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" ) type executor struct { @@ -2160,3 +2163,45 @@ func checkNep17TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rc } require.Equal(t, arr, res.Received) } + +func BenchmarkHandleIn(b *testing.B) { + chain, orc, cfg, logger := getUnitTestChain(b, false, false) + + serverConfig := network.NewServerConfig(cfg) + serverConfig.LogLevel = zapcore.FatalLevel + server, err := network.NewServer(serverConfig, chain, logger) + require.NoError(b, err) + rpcServer := New(chain, cfg.ApplicationConfiguration.RPC, server, orc, logger) + defer chain.Close() + + do := func(b *testing.B, req []byte) { + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + b.StopTimer() + in := new(request.In) + b.StartTimer() + err := json.Unmarshal(req, in) + if err != nil { + b.FailNow() + } + + res := rpcServer.handleIn(in, nil) + if res.Error != nil { + b.FailNow() + } + } + b.StopTimer() + } + + b.Run("no extra params", func(b *testing.B) { + do(b, []byte(`{"jsonrpc":"2.0", "method":"validateaddress","params":["Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2"]}`)) + }) + + b.Run("with extra params", func(b *testing.B) { + do(b, []byte(`{"jsonrpc":"2.0", "method":"validateaddress","params":["Nbb1qkwcwNSBs9pAnrVVrnFbWnbWBk91U2", +"set", "of", "different", "parameters", "to", "see", "the", "difference", "between", "unmarshalling", "algorithms", 1234, 5678, 1234567, 765432, true, false, null, +"0x50befd26fdf6e4d957c11e078b24ebce6291456f", "someMethod", [{"type": "String", "value": "50befd26fdf6e4d957c11e078b24ebce6291456f"}, +{"type": "Integer", "value": "42"}, {"type": "Boolean", "value": false}]]}`)) + }) +}