diff --git a/x/incentives/keeper/distribute.go b/x/incentives/keeper/distribute.go index a20b6d6f95c..f43801f8b2b 100644 --- a/x/incentives/keeper/distribute.go +++ b/x/incentives/keeper/distribute.go @@ -773,7 +773,7 @@ func (k Keeper) handleGroupPostDistribute(ctx sdk.Context, groupGauge types.Gaug } // getDistributeToBaseLocks takes a gauge along with cached period locks by denom and returns locks that must be distributed to -func (k Keeper) getDistributeToBaseLocks(ctx sdk.Context, gauge types.Gauge, cache map[string][]lockuptypes.PeriodLock) []*lockuptypes.PeriodLock { +func (k Keeper) getDistributeToBaseLocks(ctx sdk.Context, gauge types.Gauge, cache map[string][]lockuptypes.PeriodLock, scratchSlice *[]*lockuptypes.PeriodLock) []*lockuptypes.PeriodLock { // if gauge is empty, don't get the locks if gauge.Coins.Empty() { return []*lockuptypes.PeriodLock{} @@ -788,7 +788,7 @@ func (k Keeper) getDistributeToBaseLocks(ctx sdk.Context, gauge types.Gauge, cac // get this from memory instead of hitting iterators / underlying stores. // due to many details of cacheKVStore, iteration will still cause expensive IAVL reads. allLocks := cache[distributeBaseDenom] - return FilterLocksByMinDuration(allLocks, gauge.DistributeTo.Duration) + return FilterLocksByMinDuration(allLocks, gauge.DistributeTo.Duration, scratchSlice) } // Distribute distributes coins from an array of gauges to all eligible locks and pools in the case of "NoLock" gauges. @@ -799,10 +799,11 @@ func (k Keeper) Distribute(ctx sdk.Context, gauges []types.Gauge) (sdk.Coins, er locksByDenomCache := make(map[string][]lockuptypes.PeriodLock) totalDistributedCoins := sdk.NewCoins() + scratchSlice := make([]*lockuptypes.PeriodLock, 0, 10000) for _, gauge := range gauges { var gaugeDistributedCoins sdk.Coins - filteredLocks := k.getDistributeToBaseLocks(ctx, gauge, locksByDenomCache) + filteredLocks := k.getDistributeToBaseLocks(ctx, gauge, locksByDenomCache, &scratchSlice) // send based on synthetic lockup coins if it's distributing to synthetic lockups var err error if lockuptypes.IsSyntheticDenom(gauge.DistributeTo.Denom) { diff --git a/x/incentives/keeper/iterator.go b/x/incentives/keeper/iterator.go index 649fca91c68..c88816df68b 100644 --- a/x/incentives/keeper/iterator.go +++ b/x/incentives/keeper/iterator.go @@ -63,8 +63,9 @@ func (k Keeper) FinishedGaugesIterator(ctx sdk.Context) sdk.Iterator { } // FilterLocksByMinDuration returns locks whose lock duration is greater than the provided minimum duration. -func FilterLocksByMinDuration(locks []lockuptypes.PeriodLock, minDuration time.Duration) []*lockuptypes.PeriodLock { - filteredLocks := make([]*lockuptypes.PeriodLock, 0, len(locks)) +func FilterLocksByMinDuration(locks []lockuptypes.PeriodLock, minDuration time.Duration, scratchSlice *[]*lockuptypes.PeriodLock) []*lockuptypes.PeriodLock { + *scratchSlice = (*scratchSlice)[:0] + filteredLocks := *scratchSlice for i := range locks { if locks[i].Duration >= minDuration { filteredLocks = append(filteredLocks, &locks[i]) diff --git a/x/incentives/keeper/iterator_test.go b/x/incentives/keeper/iterator_test.go index fe008a80c13..0b5de60ff53 100644 --- a/x/incentives/keeper/iterator_test.go +++ b/x/incentives/keeper/iterator_test.go @@ -27,7 +27,8 @@ func TestFilterLocksByMinDuration(t *testing.T) { } } - filteredLocks := keeper.FilterLocksByMinDuration(locks, minDuration) + scratchSlice := []*lockuptypes.PeriodLock{} + filteredLocks := keeper.FilterLocksByMinDuration(locks, minDuration, &scratchSlice) require.Equal(t, len(locks), len(filteredLocks))