stringutil_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package stringutil_test
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strings"
  6. "sync"
  7. "testing"
  8. "github.com/opencost/opencost/core/pkg/util/stringutil"
  9. )
  10. var oldBank sync.Map
  11. type bankTest struct {
  12. Bank func(string) string
  13. BankFunc func(string, func() string) string
  14. Clear func()
  15. }
  16. var (
  17. legacyTest = bankTest{
  18. Bank: BankLegacy,
  19. BankFunc: func(s string, f func() string) string { return s },
  20. Clear: ClearBankLegacy,
  21. }
  22. standardBankTest = bankTest{
  23. Bank: stringutil.Bank,
  24. BankFunc: stringutil.BankFunc,
  25. Clear: stringutil.ClearBank,
  26. }
  27. )
  28. // This is the old implementation of the string bank to use for comparison benchmarks
  29. func BankLegacy(s string) string {
  30. ss, _ := oldBank.LoadOrStore(s, s)
  31. return ss.(string)
  32. }
  33. func ClearBankLegacy() {
  34. oldBank = sync.Map{}
  35. }
  36. func copyString(s string) string {
  37. return string([]byte(s))
  38. }
  39. func generateBenchData(totalStrings, totalUnique int) []string {
  40. randStrings := make([]string, 0, totalStrings)
  41. r := rand.New(rand.NewSource(27644437))
  42. // create totalUnique unique strings
  43. for range totalUnique {
  44. randStrings = append(
  45. randStrings,
  46. fmt.Sprintf("%s/%s/%s", stringutil.RandSeqWith(r, 10), stringutil.RandSeqWith(r, 10), stringutil.RandSeqWith(r, 10)),
  47. )
  48. }
  49. // set the seed such that the resulting "remainder" strings are deterministic for each bench
  50. r = rand.New(rand.NewSource(1523942))
  51. // append a random selection from 0-totalUnique to the list.
  52. for range totalStrings - totalUnique {
  53. randStrings = append(randStrings, strings.Clone(randStrings[r.Intn(totalUnique)]))
  54. }
  55. // shuffle the list of strings
  56. r.Shuffle(totalStrings, func(i, j int) { randStrings[i], randStrings[j] = randStrings[j], randStrings[i] })
  57. return randStrings
  58. }
  59. func benchmarkStringBank(b *testing.B, bt bankTest, totalStrings, totalUnique int, useBankFunc bool) {
  60. b.StopTimer()
  61. randStrings := generateBenchData(totalStrings, totalUnique)
  62. b.Run(b.Name(), func(b *testing.B) {
  63. for i := 0; i < b.N; i++ {
  64. b.StartTimer()
  65. for bb := 0; bb < totalStrings; bb++ {
  66. if useBankFunc {
  67. bt.BankFunc(randStrings[bb], func() string { return randStrings[bb] })
  68. } else {
  69. bt.Bank(randStrings[bb])
  70. }
  71. }
  72. b.StopTimer()
  73. bt.Clear()
  74. //runtime.GC()
  75. //debug.FreeOSMemory()
  76. }
  77. })
  78. }
  79. func BenchmarkLegacyStringBank90PercentDuplicate(b *testing.B) {
  80. benchmarkStringBank(b, legacyTest, 1_000_000, 100_000, false)
  81. }
  82. func BenchmarkLegacyStringBank75PercentDuplicate(b *testing.B) {
  83. benchmarkStringBank(b, legacyTest, 1_000_000, 250_000, false)
  84. }
  85. func BenchmarkLegacyStringBank50PercentDuplicate(b *testing.B) {
  86. benchmarkStringBank(b, legacyTest, 1_000_000, 100_000, false)
  87. }
  88. func BenchmarkLegacyStringBank25PercentDuplicate(b *testing.B) {
  89. benchmarkStringBank(b, legacyTest, 1_000_000, 750_000, false)
  90. }
  91. func BenchmarkLegacyStringBankNoDuplicate(b *testing.B) {
  92. benchmarkStringBank(b, legacyTest, 1_000_000, 1_000_000, false)
  93. }
  94. func BenchmarkStringBank90PercentDuplicate(b *testing.B) {
  95. benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, false)
  96. }
  97. func BenchmarkStringBank75PercentDuplicate(b *testing.B) {
  98. benchmarkStringBank(b, standardBankTest, 1_000_000, 250_000, false)
  99. }
  100. func BenchmarkStringBank50PercentDuplicate(b *testing.B) {
  101. benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, false)
  102. }
  103. func BenchmarkStringBank25PercentDuplicate(b *testing.B) {
  104. benchmarkStringBank(b, standardBankTest, 1_000_000, 750_000, false)
  105. }
  106. func BenchmarkStringBankNoDuplicate(b *testing.B) {
  107. benchmarkStringBank(b, standardBankTest, 1_000_000, 1_000_000, false)
  108. }
  109. func BenchmarkStringBankFunc90PercentDuplicate(b *testing.B) {
  110. benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, true)
  111. }
  112. func BenchmarkStringBankFunc75PercentDuplicate(b *testing.B) {
  113. benchmarkStringBank(b, standardBankTest, 1_000_000, 250_000, true)
  114. }
  115. func BenchmarkStringBankFunc50PercentDuplicate(b *testing.B) {
  116. benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, true)
  117. }
  118. func BenchmarkStringBankFunc25PercentDuplicate(b *testing.B) {
  119. benchmarkStringBank(b, standardBankTest, 1_000_000, 750_000, true)
  120. }
  121. func BenchmarkStringBankFuncNoDuplicate(b *testing.B) {
  122. benchmarkStringBank(b, standardBankTest, 1_000_000, 1_000_000, true)
  123. }