Skip to content

Commit

Permalink
Speedup TWAP pruning logic (#7415) (#7423)
Browse files Browse the repository at this point in the history
Previously we were unmarshalling the value of all records we prune,
and paying lots of time in re-formatting keys.

Instead we can gather all the data we need from the key we iterate over
(and save us expensive unmarshals - .3s to .5s depending on GC).
We also skip one key formatting, since thats the representation we
are already iterating over (.12s to .21s depending on GC).
We skip time formatting in the second key format (30ms AKA .03s)
We could save more in the second key formatting w/ more code complexity.

I'd estimate we're adding .05s of overhead, which we should measure.

The net change of this should be between .42s to .72s off of epoch,
and be state compatible.

(cherry picked from commit c5313af)

Co-authored-by: Dev Ojha <[email protected]>
  • Loading branch information
mergify[bot] and ValarDragon authored Feb 6, 2024
1 parent e244df2 commit 9693eb7
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
16 changes: 11 additions & 5 deletions x/twap/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,29 @@ func (k Keeper) pruneRecordsBeforeTimeButNewest(ctx sdk.Context, lastKeptTime ti
seenPoolAssetTriplets := map[uniqueTriplet]struct{}{}

for ; iter.Valid(); iter.Next() {
twapToRemove, err := types.ParseTwapFromBz(iter.Value())
timeIndexKey := iter.Key()
timeS, poolId, asset0, asset1, err := types.ParseFieldsFromHistoricalTimeKey(timeIndexKey)
if err != nil {
return err
}

poolKey := uniqueTriplet{
poolId: twapToRemove.PoolId,
asset0: twapToRemove.Asset0Denom,
asset1: twapToRemove.Asset1Denom,
poolId,
asset0,
asset1,
}
_, hasSeenPoolRecord := seenPoolAssetTriplets[poolKey]
if !hasSeenPoolRecord {
seenPoolAssetTriplets[poolKey] = struct{}{}
continue
}

k.DeleteHistoricalRecord(ctx, twapToRemove)
// Now we need to delete the historical record, formatted by both historical time and pool index.
// We already are iterating over the historical time index, so we delete that key. Then we
// reformat the key to delete the historical pool index key.
store.Delete(timeIndexKey)
poolIndexKey := types.FormatHistoricalPoolIndexTWAPKeyFromStrTime(poolId, asset0, asset1, timeS)
store.Delete(poolIndexKey)
}
return nil
}
Expand Down
26 changes: 24 additions & 2 deletions x/twap/types/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"strconv"
time "time"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -66,12 +67,33 @@ func FormatHistoricalTimeIndexTWAPKey(accumulatorWriteTime time.Time, poolId uin
}

func FormatHistoricalPoolIndexTWAPKey(poolId uint64, denom1, denom2 string, accumulatorWriteTime time.Time) []byte {
var buffer bytes.Buffer
timeS := osmoutils.FormatTimeString(accumulatorWriteTime)
fmt.Fprintf(&buffer, "%s%d%s%s%s%s%s%s", HistoricalTWAPPoolIndexPrefix, poolId, KeySeparator, denom1, KeySeparator, denom2, KeySeparator, timeS)
return FormatHistoricalPoolIndexTWAPKeyFromStrTime(poolId, denom1, denom2, timeS)
}

func FormatHistoricalPoolIndexTWAPKeyFromStrTime(poolId uint64, denom1, denom2 string, accumulatorWriteTimeString string) []byte {
var buffer bytes.Buffer
fmt.Fprintf(&buffer, "%s%d%s%s%s%s%s%s", HistoricalTWAPPoolIndexPrefix, poolId, KeySeparator, denom1, KeySeparator, denom2, KeySeparator, accumulatorWriteTimeString)
return buffer.Bytes()
}

// returns timeString, poolIdString, denom1, denom2, error
// nolint: revive
func ParseFieldsFromHistoricalTimeKey(bz []byte) (string, uint64, string, string, error) {
split := bytes.Split(bz, []byte(KeySeparator))
if len(split) != 5 {
return "", 0, "", "", errors.New("invalid key")
}
timeS := string(split[1])
poolId, err := strconv.Atoi(string(split[2]))
if err != nil {
return "", 0, "", "", err
}
denom1 := string(split[3])
denom2 := string(split[4])
return timeS, uint64(poolId), denom1, denom2, err
}

func FormatHistoricalPoolIndexTimePrefix(poolId uint64, denom1, denom2 string) []byte {
return []byte(fmt.Sprintf("%s%d%s%s%s%s%s", HistoricalTWAPPoolIndexPrefix, poolId, KeySeparator, denom1, KeySeparator, denom2, KeySeparator))
}
Expand Down

0 comments on commit 9693eb7

Please sign in to comment.