github.com/cosmos/cosmos-sdk@v0.50.10/types/coin_benchmark_test.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"cosmossdk.io/math"
     8  )
     9  
    10  func coinName(suffix int) string {
    11  	return fmt.Sprintf("coinz%04d", suffix)
    12  }
    13  
    14  func BenchmarkCoinsAdditionIntersect(b *testing.B) {
    15  	b.ReportAllocs()
    16  	benchmarkingFunc := func(numCoinsA, numCoinsB int) func(b *testing.B) {
    17  		return func(b *testing.B) {
    18  			b.ReportAllocs()
    19  			coinsA := Coins(make([]Coin, numCoinsA))
    20  			coinsB := Coins(make([]Coin, numCoinsB))
    21  
    22  			for i := 0; i < numCoinsA; i++ {
    23  				coinsA[i] = NewCoin(coinName(i), math.NewInt(int64(i)))
    24  			}
    25  			for i := 0; i < numCoinsB; i++ {
    26  				coinsB[i] = NewCoin(coinName(i), math.NewInt(int64(i)))
    27  			}
    28  
    29  			b.ResetTimer()
    30  
    31  			for i := 0; i < b.N; i++ {
    32  				coinsA.Add(coinsB...)
    33  			}
    34  		}
    35  	}
    36  
    37  	benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}}
    38  	for i := 0; i < len(benchmarkSizes); i++ {
    39  		sizeA := benchmarkSizes[i][0]
    40  		sizeB := benchmarkSizes[i][1]
    41  		b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
    42  	}
    43  }
    44  
    45  func BenchmarkCoinsAdditionNoIntersect(b *testing.B) {
    46  	b.ReportAllocs()
    47  	benchmarkingFunc := func(numCoinsA, numCoinsB int) func(b *testing.B) {
    48  		return func(b *testing.B) {
    49  			b.ReportAllocs()
    50  			coinsA := Coins(make([]Coin, numCoinsA))
    51  			coinsB := Coins(make([]Coin, numCoinsB))
    52  
    53  			for i := 0; i < numCoinsA; i++ {
    54  				coinsA[i] = NewCoin(coinName(numCoinsB+i), math.NewInt(int64(i)))
    55  			}
    56  			for i := 0; i < numCoinsB; i++ {
    57  				coinsB[i] = NewCoin(coinName(i), math.NewInt(int64(i)))
    58  			}
    59  
    60  			b.ResetTimer()
    61  
    62  			for i := 0; i < b.N; i++ {
    63  				coinsA.Add(coinsB...)
    64  			}
    65  		}
    66  	}
    67  
    68  	benchmarkSizes := [][]int{{1, 1}, {5, 5}, {5, 20}, {1, 1000}, {2, 1000}, {1000, 2}}
    69  	for i := 0; i < len(benchmarkSizes); i++ {
    70  		sizeA := benchmarkSizes[i][0]
    71  		sizeB := benchmarkSizes[i][1]
    72  		b.Run(fmt.Sprintf("sizes: A_%d, B_%d", sizeA, sizeB), benchmarkingFunc(sizeA, sizeB))
    73  	}
    74  }
    75  
    76  func BenchmarkSumOfCoinAdds(b *testing.B) {
    77  	// This benchmark tests the performance of adding a large number of coins
    78  	// into a single coin set.
    79  	// it does numAdds additions, each addition has (numIntersectingCoins) that contain denoms
    80  	// already in the sum, and (coinsPerAdd - numIntersectingCoins) that are new denoms.
    81  	benchmarkingFunc := func(numAdds, coinsPerAdd, numIntersectingCoins int, sumFn func([]Coins) Coins) func(b *testing.B) {
    82  		return func(b *testing.B) {
    83  			b.ReportAllocs()
    84  			addCoins := make([]Coins, numAdds)
    85  			nonIntersectingCoins := coinsPerAdd - numIntersectingCoins
    86  
    87  			for i := 0; i < numAdds; i++ {
    88  				intersectCoins := make([]Coin, numIntersectingCoins)
    89  				num := math.NewInt(int64(i))
    90  				for j := 0; j < numIntersectingCoins; j++ {
    91  					intersectCoins[j] = NewCoin(coinName(j+1_000_000_000), num)
    92  				}
    93  				addCoins[i] = intersectCoins
    94  				for j := 0; j < nonIntersectingCoins; j++ {
    95  					addCoins[i] = addCoins[i].Add(NewCoin(coinName(i*nonIntersectingCoins+j), num))
    96  				}
    97  			}
    98  
    99  			b.ResetTimer()
   100  
   101  			for i := 0; i < b.N; i++ {
   102  				sumFn(addCoins)
   103  			}
   104  		}
   105  	}
   106  
   107  	MapCoinsSumFn := func(coins []Coins) Coins {
   108  		sum := MapCoins{}
   109  		for _, coin := range coins {
   110  			sum.Add(coin...)
   111  		}
   112  		return sum.ToCoins()
   113  	}
   114  	CoinsSumFn := func(coins []Coins) Coins {
   115  		sum := Coins{}
   116  		for _, coin := range coins {
   117  			sum = sum.Add(coin...)
   118  		}
   119  		return sum
   120  	}
   121  
   122  	// larger benchmarks with non-overlapping coins won't terminate in reasonable timeframes with sdk.Coins
   123  	// they work fine with MapCoins
   124  	benchmarkSizes := [][]int{{5, 2, 1000}, {10, 10, 10000}}
   125  	sumFns := []struct {
   126  		name string
   127  		fn   func([]Coins) Coins
   128  	}{
   129  		{"MapCoins", MapCoinsSumFn}, {"Coins", CoinsSumFn},
   130  	}
   131  	for i := 0; i < len(benchmarkSizes); i++ {
   132  		for j := 0; j < 2; j++ {
   133  			coinsPerAdd := benchmarkSizes[i][0]
   134  			intersectingCoinsPerAdd := benchmarkSizes[i][1]
   135  			numAdds := benchmarkSizes[i][2]
   136  			sumFn := sumFns[j]
   137  			b.Run(fmt.Sprintf("Fn: %s, num adds: %d, coinsPerAdd: %d, intersecting: %d",
   138  				sumFn.name, numAdds, coinsPerAdd, intersectingCoinsPerAdd),
   139  				benchmarkingFunc(numAdds, coinsPerAdd, intersectingCoinsPerAdd, sumFn.fn))
   140  		}
   141  	}
   142  }