From 4d043675deeac305e5f0ebcf9850925bc8248032 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 16 Sep 2021 15:06:21 +0200 Subject: [PATCH] perf: Speedup coins.AmountOf() by removing many regex calls (backport #10021) (#10166) * perf: Speedup coins.AmountOf() by removing many regex calls (#10021) (cherry picked from commit ed35bfdf52ec18af497fc04787cdb509562af95e) # Conflicts: # CHANGELOG.md * fix conflict * fix changelog Co-authored-by: Dev Ojha Co-authored-by: Robert Zaremba --- CHANGELOG.md | 3 +++ types/coin.go | 18 ++++-------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb66886b404..d5880ab449a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements +* (types) [\#10021](https://github.com/cosmos/cosmos-sdk/pull/10021) Speedup coins.AmountOf(), by removing many intermittent regex calls. + ### Bug Fixes * (x/genutil) [#10104](https://github.com/cosmos/cosmos-sdk/pull/10104) Ensure the `init` command reads the `--home` flag value correctly. diff --git a/types/coin.go b/types/coin.go index 19e002ff0f41..f6627c4c3a81 100644 --- a/types/coin.go +++ b/types/coin.go @@ -701,18 +701,7 @@ func (coins Coins) AmountOf(denom string) math.Int { // AmountOfNoDenomValidation returns the amount of a denom from coins // without validating the denomination. -// CONTRACT: coins must be valid (sorted). -func (coins Coins) AmountOfNoDenomValidation(denom string) math.Int { - if ok, c := coins.Find(denom); ok { - return c.Amount - } - return math.ZeroInt() -} - -// Find returns true and coin if the denom exists in coins. Otherwise it returns false -// and a zero coin. Uses binary search. -// CONTRACT: coins must be valid (sorted). -func (coins Coins) Find(denom string) (bool, Coin) { +func (coins Coins) AmountOfNoDenomValidation(denom string) Int { switch len(coins) { case 0: return false, Coin{} @@ -725,15 +714,16 @@ func (coins Coins) Find(denom string) (bool, Coin) { return false, Coin{} default: + // Binary search the amount of coins remaining midIdx := len(coins) / 2 // 2:1, 3:1, 4:2 coin := coins[midIdx] switch { case denom < coin.Denom: - return coins[:midIdx].Find(denom) + return coins[:midIdx].AmountOfNoDenomValidation(denom) case denom == coin.Denom: return true, coin default: - return coins[midIdx+1:].Find(denom) + return coins[midIdx+1:].AmountOfNoDenomValidation(denom) } } }