perf!: Add HasAccount to the AuthKeeper to save protobuf decoding time (backport #10022) (#10847)

* perf!: Add HasAccount to the AuthKeeper to save protobuf decoding time (#10022)

* Add HasAccount to the AuthKeeper to save protobuf decoding time

We found in the Osmosis epoch time, the many accesses to GetAccount's proto unmarshalling was a significant slowdown.
This adds a HasAccount method to the AuthKeeper, and fixes one unnecessary spot that it appears within in SendCoins

* Update Spec

* Add Changelog entry

* Fix lint & use speedup in SendCoins

* Update x/auth/keeper/account.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
(cherry picked from commit 7273bd39e7)

# Conflicts:
#	CHANGELOG.md

* conflicts

* changelog

* changelog

Co-authored-by: Dev Ojha <ValarDragon@users.noreply.github.com>
Co-authored-by: Federico Kunze Küllmer <federico.kunze94@gmail.com>
This commit is contained in:
mergify[bot] 2021-12-31 01:51:29 +01:00 committed by GitHub
parent 8ad8d5df4d
commit 1321bc1614
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 21 additions and 4 deletions

View File

@ -44,6 +44,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (store) [#10218](https://github.com/cosmos/cosmos-sdk/pull/10218) Charge gas even when there are no entries while seeking. * (store) [#10218](https://github.com/cosmos/cosmos-sdk/pull/10218) Charge gas even when there are no entries while seeking.
* (store) [#10247](https://github.com/cosmos/cosmos-sdk/pull/10247) Charge gas for the key length in gas meter. * (store) [#10247](https://github.com/cosmos/cosmos-sdk/pull/10247) Charge gas for the key length in gas meter.
### API Breaking Changes
* (auth) [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `AuthKeeper` interface in `x/auth` now includes a function `HasAccount`.
### Improvements ### Improvements
* (store) [\#10741](https://github.com/cosmos/cosmos-sdk/pull/10741) Significantly speedup iterator creation after delete heavy workloads. Significantly improves IBC migration times. * (store) [\#10741](https://github.com/cosmos/cosmos-sdk/pull/10741) Significantly speedup iterator creation after delete heavy workloads. Significantly improves IBC migration times.

View File

@ -25,6 +25,12 @@ func (ak AccountKeeper) NewAccount(ctx sdk.Context, acc types.AccountI) types.Ac
return acc return acc
} }
// HasAccount implements AccountKeeperI.
func (ak AccountKeeper) HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool {
store := ctx.KVStore(ak.key)
return store.Has(types.AddressStoreKey(addr))
}
// GetAccount implements AccountKeeperI. // GetAccount implements AccountKeeperI.
func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI { func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI {
store := ctx.KVStore(ak.key) store := ctx.KVStore(ak.key)

View File

@ -22,6 +22,9 @@ type AccountKeeperI interface {
// Return a new account with the next account number. Does not save the new account to the store. // Return a new account with the next account number. Does not save the new account to the store.
NewAccount(sdk.Context, types.AccountI) types.AccountI NewAccount(sdk.Context, types.AccountI) types.AccountI
// Check if an account exists in the store.
HasAccount(sdk.Context, sdk.AccAddress) bool
// Retrieve an account from the store. // Retrieve an account from the store.
GetAccount(sdk.Context, sdk.AccAddress) types.AccountI GetAccount(sdk.Context, sdk.AccAddress) types.AccountI

View File

@ -20,6 +20,9 @@ type AccountKeeperI interface {
// Return a new account with the next account number. Does not save the new account to the store. // Return a new account with the next account number. Does not save the new account to the store.
NewAccount(sdk.Context, types.AccountI) types.AccountI NewAccount(sdk.Context, types.AccountI) types.AccountI
// Check if an account exists in the store.
HasAccount(sdk.Context, sdk.AccAddress) bool
// Retrieve an account from the store. // Retrieve an account from the store.
GetAccount(sdk.Context, sdk.AccAddress) types.AccountI GetAccount(sdk.Context, sdk.AccAddress) types.AccountI

View File

@ -118,8 +118,8 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input,
// //
// NOTE: This should ultimately be removed in favor a more flexible approach // NOTE: This should ultimately be removed in favor a more flexible approach
// such as delegated fee messages. // such as delegated fee messages.
acc := k.ak.GetAccount(ctx, outAddress) accExists := k.ak.HasAccount(ctx, outAddress)
if acc == nil { if !accExists {
defer telemetry.IncrCounter(1, "new", "account") defer telemetry.IncrCounter(1, "new", "account")
k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, outAddress)) k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, outAddress))
} }
@ -145,8 +145,8 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd
// //
// NOTE: This should ultimately be removed in favor a more flexible approach // NOTE: This should ultimately be removed in favor a more flexible approach
// such as delegated fee messages. // such as delegated fee messages.
acc := k.ak.GetAccount(ctx, toAddr) accExists := k.ak.HasAccount(ctx, toAddr)
if acc == nil { if !accExists {
defer telemetry.IncrCounter(1, "new", "account") defer telemetry.IncrCounter(1, "new", "account")
k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, toAddr)) k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, toAddr))
} }

View File

@ -13,6 +13,7 @@ type AccountKeeper interface {
GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI
GetAllAccounts(ctx sdk.Context) []types.AccountI GetAllAccounts(ctx sdk.Context) []types.AccountI
HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool
SetAccount(ctx sdk.Context, acc types.AccountI) SetAccount(ctx sdk.Context, acc types.AccountI)
IterateAccounts(ctx sdk.Context, process func(types.AccountI) bool) IterateAccounts(ctx sdk.Context, process func(types.AccountI) bool)