From 46119d1384e48a04a491905ba41c401548ee858b Mon Sep 17 00:00:00 2001 From: Lukasz Cwik <126621805+lcwik@users.noreply.github.com> Date: Wed, 17 May 2023 11:10:20 -0700 Subject: [PATCH] perf: Create Ante/Post handler chain once. (#16076) Co-authored-by: Aleksandr Bezobchuk --- CHANGELOG.md | 1 + types/handler.go | 33 +++++++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6e4f612921..b1302ef03984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (types) [#16076](https://github.com/cosmos/cosmos-sdk/pull/16076) Optimize `ChainAnteDecorators`/`ChainPostDecorators` to instantiate the functions once instead of on every invocation of the returned `AnteHandler`/`PostHandler`. * (client) [#16075](https://github.com/cosmos/cosmos-sdk/pull/16075) Partly revert [#15953](https://github.com/cosmos/cosmos-sdk/issues/15953) and `factory.Prepare` does nothing in offline mode. * (server) [#16071](https://github.com/cosmos/cosmos-sdk/pull/16071) When `mempool.max-txs` is set to a negative value, use a no-op mempool (effectively disable the app mempool). * (simapp) [#15958](https://github.com/cosmos/cosmos-sdk/pull/15958) Refactor SimApp for removing the global basic manager. diff --git a/types/handler.go b/types/handler.go index 1a86c1660551..7b57dd52f599 100644 --- a/types/handler.go +++ b/types/handler.go @@ -40,14 +40,19 @@ func ChainAnteDecorators(chain ...AnteDecorator) AnteHandler { return nil } - // handle non-terminated decorators chain - if (chain[len(chain)-1] != Terminator{}) { - chain = append(chain, Terminator{}) + handlerChain := make([]AnteHandler, len(chain)+1) + // set the terminal AnteHandler decorator + handlerChain[len(chain)] = func(ctx Context, tx Tx, simulate bool) (Context, error) { + return ctx, nil } - - return func(ctx Context, tx Tx, simulate bool) (Context, error) { - return chain[0].AnteHandle(ctx, tx, simulate, ChainAnteDecorators(chain[1:]...)) + for i := 0; i < len(chain); i++ { + ii := i + handlerChain[ii] = func(ctx Context, tx Tx, simulate bool) (Context, error) { + return chain[ii].AnteHandle(ctx, tx, simulate, handlerChain[ii+1]) + } } + + return handlerChain[0] } // ChainPostDecorators chains PostDecorators together with each PostDecorator @@ -63,14 +68,18 @@ func ChainPostDecorators(chain ...PostDecorator) PostHandler { return nil } - // handle non-terminated decorators chain - if (chain[len(chain)-1] != Terminator{}) { - chain = append(chain, Terminator{}) + handlerChain := make([]PostHandler, len(chain)+1) + // set the terminal PostHandler decorator + handlerChain[len(chain)] = func(ctx Context, tx Tx, simulate, success bool) (Context, error) { + return ctx, nil } - - return func(ctx Context, tx Tx, simulate, success bool) (Context, error) { - return chain[0].PostHandle(ctx, tx, simulate, success, ChainPostDecorators(chain[1:]...)) + for i := 0; i < len(chain); i++ { + ii := i + handlerChain[ii] = func(ctx Context, tx Tx, simulate, success bool) (Context, error) { + return chain[ii].PostHandle(ctx, tx, simulate, success, handlerChain[ii+1]) + } } + return handlerChain[0] } // Terminator AnteDecorator will get added to the chain to simplify decorator code