|
|
@@ -1,16 +1,37 @@
|
|
|
-package stringutil
|
|
|
+package stringutil_test
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
"math/rand"
|
|
|
- "runtime"
|
|
|
- "runtime/debug"
|
|
|
+ "strings"
|
|
|
"sync"
|
|
|
"testing"
|
|
|
+
|
|
|
+ "github.com/opencost/opencost/core/pkg/util/stringutil"
|
|
|
)
|
|
|
|
|
|
var oldBank sync.Map
|
|
|
|
|
|
+type bankTest struct {
|
|
|
+ Bank func(string) string
|
|
|
+ BankFunc func(string, func() string) string
|
|
|
+ Clear func()
|
|
|
+}
|
|
|
+
|
|
|
+var (
|
|
|
+ legacyTest = bankTest{
|
|
|
+ Bank: BankLegacy,
|
|
|
+ BankFunc: func(s string, f func() string) string { return s },
|
|
|
+ Clear: ClearBankLegacy,
|
|
|
+ }
|
|
|
+
|
|
|
+ standardBankTest = bankTest{
|
|
|
+ Bank: stringutil.Bank,
|
|
|
+ BankFunc: stringutil.BankFunc,
|
|
|
+ Clear: stringutil.ClearBank,
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
// This is the old implementation of the string bank to use for comparison benchmarks
|
|
|
func BankLegacy(s string) string {
|
|
|
ss, _ := oldBank.LoadOrStore(s, s)
|
|
|
@@ -27,118 +48,108 @@ func copyString(s string) string {
|
|
|
|
|
|
func generateBenchData(totalStrings, totalUnique int) []string {
|
|
|
randStrings := make([]string, 0, totalStrings)
|
|
|
+ r := rand.New(rand.NewSource(27644437))
|
|
|
|
|
|
// create totalUnique unique strings
|
|
|
- for i := 0; i < totalUnique; i++ {
|
|
|
- randStrings = append(randStrings, fmt.Sprintf("%s/%s/%s", RandSeq(10), RandSeq(10), RandSeq(10)))
|
|
|
+ for range totalUnique {
|
|
|
+ randStrings = append(
|
|
|
+ randStrings,
|
|
|
+ fmt.Sprintf("%s/%s/%s", stringutil.RandSeqWith(r, 10), stringutil.RandSeqWith(r, 10), stringutil.RandSeqWith(r, 10)),
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
// set the seed such that the resulting "remainder" strings are deterministic for each bench
|
|
|
- rand.Seed(1523942)
|
|
|
+ r = rand.New(rand.NewSource(1523942))
|
|
|
|
|
|
// append a random selection from 0-totalUnique to the list.
|
|
|
- for i := 0; i < totalStrings-totalUnique; i++ {
|
|
|
- randStrings = append(randStrings, copyString(randStrings[rand.Intn(totalUnique)]))
|
|
|
+ for range totalStrings - totalUnique {
|
|
|
+ randStrings = append(randStrings, strings.Clone(randStrings[r.Intn(totalUnique)]))
|
|
|
}
|
|
|
|
|
|
// shuffle the list of strings
|
|
|
- rand.Shuffle(totalStrings, func(i, j int) { randStrings[i], randStrings[j] = randStrings[j], randStrings[i] })
|
|
|
+ r.Shuffle(totalStrings, func(i, j int) { randStrings[i], randStrings[j] = randStrings[j], randStrings[i] })
|
|
|
|
|
|
return randStrings
|
|
|
}
|
|
|
|
|
|
-func benchmarkLegacyStringBank(b *testing.B, totalStrings, totalUnique int) {
|
|
|
+func benchmarkStringBank(b *testing.B, bt bankTest, totalStrings, totalUnique int, useBankFunc bool) {
|
|
|
b.StopTimer()
|
|
|
randStrings := generateBenchData(totalStrings, totalUnique)
|
|
|
|
|
|
- for i := 0; i < b.N; i++ {
|
|
|
- b.StartTimer()
|
|
|
- for b := 0; b < totalStrings; b++ {
|
|
|
- BankLegacy(randStrings[b])
|
|
|
- }
|
|
|
- b.StopTimer()
|
|
|
- ClearBankLegacy()
|
|
|
- runtime.GC()
|
|
|
- debug.FreeOSMemory()
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func benchmarkStringBank(b *testing.B, totalStrings, totalUnique int, useBankFunc bool) {
|
|
|
- b.StopTimer()
|
|
|
- randStrings := generateBenchData(totalStrings, totalUnique)
|
|
|
-
|
|
|
- for i := 0; i < b.N; i++ {
|
|
|
- b.StartTimer()
|
|
|
- for b := 0; b < totalStrings; b++ {
|
|
|
- if useBankFunc {
|
|
|
- BankFunc(randStrings[b], func() string { return randStrings[b] })
|
|
|
- } else {
|
|
|
- Bank(randStrings[b])
|
|
|
+ b.Run(b.Name(), func(b *testing.B) {
|
|
|
+ for i := 0; i < b.N; i++ {
|
|
|
+ b.StartTimer()
|
|
|
+ for bb := 0; bb < totalStrings; bb++ {
|
|
|
+ if useBankFunc {
|
|
|
+ bt.BankFunc(randStrings[bb], func() string { return randStrings[bb] })
|
|
|
+ } else {
|
|
|
+ bt.Bank(randStrings[bb])
|
|
|
+ }
|
|
|
}
|
|
|
+ b.StopTimer()
|
|
|
+ bt.Clear()
|
|
|
+ //runtime.GC()
|
|
|
+ //debug.FreeOSMemory()
|
|
|
}
|
|
|
- b.StopTimer()
|
|
|
- ClearBank()
|
|
|
- runtime.GC()
|
|
|
- debug.FreeOSMemory()
|
|
|
- }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
func BenchmarkLegacyStringBank90PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkLegacyStringBank(b, 1_000_000, 100_000)
|
|
|
+ benchmarkStringBank(b, legacyTest, 1_000_000, 100_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkLegacyStringBank75PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkLegacyStringBank(b, 1_000_000, 250_000)
|
|
|
+ benchmarkStringBank(b, legacyTest, 1_000_000, 250_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkLegacyStringBank50PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkLegacyStringBank(b, 1_000_000, 100_000)
|
|
|
+ benchmarkStringBank(b, legacyTest, 1_000_000, 100_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkLegacyStringBank25PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkLegacyStringBank(b, 1_000_000, 750_000)
|
|
|
+ benchmarkStringBank(b, legacyTest, 1_000_000, 750_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkLegacyStringBankNoDuplicate(b *testing.B) {
|
|
|
- benchmarkLegacyStringBank(b, 1_000_000, 1_000_000)
|
|
|
+ benchmarkStringBank(b, legacyTest, 1_000_000, 1_000_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBank90PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 100_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBank75PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 250_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 250_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBank50PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 100_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBank25PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 750_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 750_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankNoDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 1_000_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 1_000_000, false)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankFunc90PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 100_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, true)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankFunc75PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 250_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 250_000, true)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankFunc50PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 100_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 100_000, true)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankFunc25PercentDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 750_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 750_000, true)
|
|
|
}
|
|
|
|
|
|
func BenchmarkStringBankFuncNoDuplicate(b *testing.B) {
|
|
|
- benchmarkStringBank(b, 1_000_000, 1_000_000, false)
|
|
|
+ benchmarkStringBank(b, standardBankTest, 1_000_000, 1_000_000, true)
|
|
|
}
|