Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Last active March 19, 2025 12:09
Show Gist options
  • Save mikeschinkel/2f848e25ca383d9bb76fd60e8c7b0a4f to your computer and use it in GitHub Desktop.
Save mikeschinkel/2f848e25ca383d9bb76fd60e8c7b0a4f to your computer and use it in GitHub Desktop.
Test for Peformance of SwitchCase vs. IfOr vs. Generic for Determining Membership in Golang
package main_test
import (
"testing"
)
type Lexer struct {
input string // the string being scanned.
pos int // current position in the input.
}
func (l *Lexer) char() byte {
return l.input[l.pos]
}
func (l *Lexer) withPos(n int) *Lexer {
l.pos = n
return l
}
func Is[T comparable](s T, vals ...T) bool {
for _, v := range vals {
if s == v {
return true
}
}
return false
}
const (
firstSmallCharConst = ' '
midSmallCharConst = '\t'
lastSmallCharConst = '\n'
firstLargeCharConst = 'a'
midLargeCharConst = 'j'
lastLargeCharConst = 'z'
noMatchSmallCharConst = 'x'
noMatchLargeCharConst = '-'
)
var (
firstSmallCharVar = firstSmallCharConst
midSmallCharVar = midSmallCharConst
lastSmallCharVar = lastSmallCharConst
firstLargeCharVar = firstLargeCharConst
midLargeCharVar = midLargeCharConst
lastLargeCharVar = lastLargeCharConst
noMatchSmallCharVar = noMatchSmallCharConst
noMatchLargeCharVar = noMatchLargeCharConst
firstLex = &Lexer{input: " \t\n", pos: 0}
midLex = firstLex.withPos(1)
lastLex = firstLex.withPos(2)
noMatchLex = &Lexer{input: "xyz", pos: 0}
)
var (
exprOR = func(c rune) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
}
exprORLarger = func(c rune) bool {
return c == 'a' || c == 'q' || c == 'r' || c == 'd' || c == 'w' || c == 'f' || c == 't' || c == 'b' || c == 'y' || c == 'z'
}
exprORMethod = func(lex *Lexer) bool {
return lex.char() == ' ' || lex.char() == '\t' || lex.char() == '\n'
}
exprORMethodLarger = func(lex *Lexer) bool {
return lex.char() == 'a' || lex.char() == 'q' || lex.char() == 'r' || lex.char() == 'd' || lex.char() == 'w' || lex.char() == 'f' || lex.char() == 't' || lex.char() == 'b' || lex.char() == 'y' || lex.char() == 'z'
}
switchCase = func(c rune) bool {
switch c {
case ' ', '\t', '\n':
return true
}
return false
}
switchCaseLarger = func(c rune) bool {
switch c {
case 'a', 'q', 'r', 'd', 'w', 'f', 't', 'b', 'y', 'z':
return true
}
return false
}
switchCaseMethod = func(lex *Lexer) bool {
switch lex.char() {
case ' ', '\t', '\n':
return true
}
return false
}
switchCaseMethodLarger = func(lex *Lexer) bool {
switch lex.char() {
case 'a', 'q', 'r', 'd', 'w', 'f', 't', 'b', 'y', 'z':
return true
}
return false
}
genericIs = func(c rune) bool {
return Is(c, ' ', '\t', '\n')
}
genericIsMethod = func(lex *Lexer) bool {
return Is(lex.char(), ' ', '\t', '\n')
}
genericIsLarger = func(c rune) bool {
return Is(c, 'a', 'q', 'r', 'd', 'w', 'f', 't', 'b', 'y', 'z')
}
genericIsMethodLarger = func(lex *Lexer) bool {
return Is(lex.char(), 'a', 'q', 'r', 'd', 'w', 'f', 't', 'b', 'y', 'z')
}
)
func BenchmarkValueMembership(b *testing.B) {
b.Run("Smaller", func(b *testing.B) {
b.Run("ExprOR", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, First, Literal
_ = exprOR(' ')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, First, Const
_ = exprOR(firstSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, First, Var
_ = exprOR(firstSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, First, Method
_ = exprORMethod(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Middle, Literal
_ = exprOR('\t')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Middle, Const
_ = exprOR(midSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Middle, Var
_ = exprOR(midSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Middle, Method
_ = exprORMethod(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Last, Literal
_ = exprOR('\n')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Last, Const
_ = exprOR(lastSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Last, Var
_ = exprOR(lastSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, Last, Method
_ = exprORMethod(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, NoMatch, Literal
_ = exprOR('x')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, NoMatch, Const
_ = exprOR(noMatchSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, NoMatch, Var
_ = exprOR(noMatchSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, ExprOR, NoMatch, Method
_ = exprORMethod(noMatchLex)
}
})
})
})
b.Run("SwitchCase", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, First, Literal
_ = switchCase(' ')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, First, Const
_ = switchCase(firstSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, First, Var
_ = switchCase(firstSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, First, Method
_ = switchCaseMethod(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Middle, Literal
_ = switchCase('\t')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Middle, Const
_ = switchCase(midSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Middle, Var
_ = switchCase(midSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Middle, Method
_ = switchCaseMethod(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Last, Literal
_ = switchCase('\n')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Last, Const
_ = switchCase(lastSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Last, Var
_ = switchCase(lastSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, Last, Method
_ = switchCaseMethod(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, NoMatch, Literal
_ = switchCase('x')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, NoMatch, Const
_ = switchCase(noMatchSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, NoMatch, Var
_ = switchCase(noMatchSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, SwitchCase, NoMatch, Method
_ = switchCaseMethod(noMatchLex)
}
})
})
})
b.Run("GenericIs", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, First, Literal
_ = genericIs(' ')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, First, Const
_ = genericIs(firstSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, First, Var
_ = genericIs(firstSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, First, Method
_ = genericIsMethod(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Middle, Literal
_ = genericIs('\t')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Middle, Const
_ = genericIs(midSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Middle, Var
_ = genericIs(midSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Middle, Method
_ = genericIsMethod(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Last, Literal
_ = genericIs('\n')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Last, Const
_ = genericIs(lastSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Last, Var
_ = genericIs(lastSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, Last, Method
_ = genericIsMethod(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, NoMatch, Literal
_ = genericIs('x')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, NoMatch, Const
_ = genericIs(noMatchSmallCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, NoMatch, Var
_ = genericIs(noMatchSmallCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Smaller, GenericIs, NoMatch, Method
_ = genericIsMethod(noMatchLex)
}
})
})
})
})
b.Run("Larger", func(b *testing.B) {
b.Run("ExprOR", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, First, Literal
_ = exprORLarger('a')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, First, Const
_ = exprORLarger(firstLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, First, Var
_ = exprORLarger(firstLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, First, Method
_ = exprORMethodLarger(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Middle, Literal
_ = exprORLarger('j')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Middle, Const
_ = exprORLarger(midLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Middle, Var
_ = exprORLarger(midLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Middle, Method
_ = exprORMethodLarger(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Last, Literal
_ = exprORLarger('z')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Last, Const
_ = exprORLarger(lastLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Last, Var
_ = exprORLarger(lastLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, Last, Method
_ = exprORMethodLarger(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, NoMatch, Literal
_ = exprORLarger('-')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, NoMatch, Const
_ = exprORLarger(noMatchLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, NoMatch, Var
_ = exprORLarger(noMatchLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, ExprOR, NoMatch, Method
_ = exprORMethodLarger(noMatchLex)
}
})
})
})
b.Run("SwitchCase", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, First, Literal
_ = switchCaseLarger('a')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, First, Const
_ = switchCaseLarger(firstLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, First, Var
_ = switchCaseLarger(firstLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, First, Method
_ = switchCaseMethodLarger(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Middle, Literal
_ = switchCaseLarger('j')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Middle, Const
_ = switchCaseLarger(midLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Middle, Var
_ = switchCaseLarger(midLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Middle, Method
_ = switchCaseMethodLarger(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Last, Literal
_ = switchCaseLarger('z')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Last, Const
_ = switchCaseLarger(lastLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Last, Var
_ = switchCaseLarger(lastLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, Last, Method
_ = switchCaseMethodLarger(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, NoMatch, Literal
_ = switchCaseLarger('-')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, NoMatch, Const
_ = switchCaseLarger(noMatchLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, NoMatch, Var
_ = switchCaseLarger(noMatchLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, SwitchCase, NoMatch, Method
_ = switchCaseMethodLarger(noMatchLex)
}
})
})
})
b.Run("GenericIs", func(b *testing.B) {
b.Run("First", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, First, Literal
_ = genericIsLarger('a')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, First, Const
_ = genericIsLarger(firstLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, First, Var
_ = genericIsLarger(firstLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, First, Method
_ = genericIsMethodLarger(firstLex)
}
})
})
b.Run("Middle", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Middle, Literal
_ = genericIsLarger('j')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Middle, Const
_ = genericIsLarger(midLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Middle, Var
_ = genericIsLarger(midLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Middle, Method
_ = genericIsMethodLarger(midLex)
}
})
})
b.Run("Last", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Last, Literal
_ = genericIsLarger('z')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Last, Const
_ = genericIsLarger(lastLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Last, Var
_ = genericIsLarger(lastLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, Last, Method
_ = genericIsMethodLarger(lastLex)
}
})
})
b.Run("NoMatch", func(b *testing.B) {
b.Run("Literal", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, NoMatch, Literal
_ = genericIsLarger('-')
}
})
b.Run("Const", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, NoMatch, Const
_ = genericIsLarger(noMatchLargeCharConst)
}
})
b.Run("Var", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, NoMatch, Var
_ = genericIsLarger(noMatchLargeCharVar)
}
})
b.Run("Method", func(b *testing.B) {
for b.Loop() {
// Factors: Larger, GenericIs, NoMatch, Method
_ = genericIsMethodLarger(noMatchLex)
}
})
})
})
})
}
package main
import (
"fmt"
"strings"
)
func main() {
f := GenerateBenchmarkFunc()
print(f)
}
var (
ExprOR = "ExprOR"
Smaller = "Smaller"
First = "First"
Literal = "Literal"
NoMatch = "NoMatch"
SwitchCase = "SwitchCase"
GenericIs = "GenericIs"
Larger = "Larger"
Middle = "Middle"
Last = "Last"
Const = "Const"
Var = "Var"
Method = "Method"
)
const (
noMatchSmallChar = `x`
noMatchLargeChar = `-`
firstSmallChar = ` `
midSmallChar = `\t`
lastSmallChar = `\n`
firstLargeChar = `a`
midLargeChar = `j`
lastLargeChar = `z`
)
func GenerateBenchmark(sb *strings.Builder, factors Factors, depth int) {
var expr string
list := strings.Join(factors, ", ")
sb.WriteString(tabs(depth) + fmt.Sprintf("// Factors: %s\n", list))
switch strings.Join(factors, "") {
case Smaller + ExprOR + First + Literal:
expr = fmt.Sprintf(`exprOR('%s')`, firstSmallChar)
case Smaller + SwitchCase + First + Literal:
expr = fmt.Sprintf(`switchCase('%s')`, firstSmallChar)
case Smaller + GenericIs + First + Literal:
expr = fmt.Sprintf(`genericIs('%s')`, firstSmallChar)
case Smaller + ExprOR + Middle + Literal:
expr = fmt.Sprintf(`exprOR('%s')`, midSmallChar)
case Smaller + SwitchCase + Middle + Literal:
expr = fmt.Sprintf(`switchCase('%s')`, midSmallChar)
case Smaller + GenericIs + Middle + Literal:
expr = fmt.Sprintf(`genericIs('%s')`, midSmallChar)
case Smaller + ExprOR + Last + Literal:
expr = fmt.Sprintf(`exprOR('%s')`, lastSmallChar)
case Smaller + SwitchCase + Last + Literal:
expr = fmt.Sprintf(`switchCase('%s')`, lastSmallChar)
case Smaller + GenericIs + Last + Literal:
expr = fmt.Sprintf(`genericIs('%s')`, lastSmallChar)
case Smaller + ExprOR + NoMatch + Literal:
expr = fmt.Sprintf(`exprOR('%s')`, noMatchSmallChar)
case Smaller + SwitchCase + NoMatch + Literal:
expr = fmt.Sprintf(`switchCase('%s')`, noMatchSmallChar)
case Smaller + GenericIs + NoMatch + Literal:
expr = fmt.Sprintf(`genericIs('%s')`, noMatchSmallChar)
case Smaller + ExprOR + First + Const:
expr = `exprOR(firstSmallCharConst)`
case Smaller + SwitchCase + First + Const:
expr = `switchCase(firstSmallCharConst)`
case Smaller + GenericIs + First + Const:
expr = `genericIs(firstSmallCharConst)`
case Smaller + ExprOR + Middle + Const:
expr = `exprOR(midSmallCharConst)`
case Smaller + SwitchCase + Middle + Const:
expr = `switchCase(midSmallCharConst)`
case Smaller + GenericIs + Middle + Const:
expr = `genericIs(midSmallCharConst)`
case Smaller + ExprOR + Last + Const:
expr = `exprOR(lastSmallCharConst)`
case Smaller + SwitchCase + Last + Const:
expr = `switchCase(lastSmallCharConst)`
case Smaller + GenericIs + Last + Const:
expr = `genericIs(lastSmallCharConst)`
case Smaller + ExprOR + NoMatch + Const:
expr = `exprOR(noMatchSmallCharConst)`
case Smaller + SwitchCase + NoMatch + Const:
expr = `switchCase(noMatchSmallCharConst)`
case Smaller + GenericIs + NoMatch + Const:
expr = `genericIs(noMatchSmallCharConst)`
case Smaller + ExprOR + First + Var:
expr = `exprOR(firstSmallCharVar)`
case Smaller + SwitchCase + First + Var:
expr = `switchCase(firstSmallCharVar)`
case Smaller + GenericIs + First + Var:
expr = `genericIs(firstSmallCharVar)`
case Smaller + ExprOR + Middle + Var:
expr = `exprOR(midSmallCharVar)`
case Smaller + SwitchCase + Middle + Var:
expr = `switchCase(midSmallCharVar)`
case Smaller + GenericIs + Middle + Var:
expr = `genericIs(midSmallCharVar)`
case Smaller + ExprOR + Last + Var:
expr = `exprOR(lastSmallCharVar)`
case Smaller + SwitchCase + Last + Var:
expr = `switchCase(lastSmallCharVar)`
case Smaller + GenericIs + Last + Var:
expr = `genericIs(lastSmallCharVar)`
case Smaller + ExprOR + NoMatch + Var:
expr = `exprOR(noMatchSmallCharVar)`
case Smaller + SwitchCase + NoMatch + Var:
expr = `switchCase(noMatchSmallCharVar)`
case Smaller + GenericIs + NoMatch + Var:
expr = `genericIs(noMatchSmallCharVar)`
case Smaller + ExprOR + First + Method:
expr = `exprORMethod(firstLex)`
case Smaller + SwitchCase + First + Method:
expr = `switchCaseMethod(firstLex)`
case Smaller + GenericIs + First + Method:
expr = `genericIsMethod(firstLex)`
case Smaller + ExprOR + Middle + Method:
expr = `exprORMethod(midLex)`
case Smaller + SwitchCase + Middle + Method:
expr = `switchCaseMethod(midLex)`
case Smaller + GenericIs + Middle + Method:
expr = `genericIsMethod(midLex)`
case Smaller + ExprOR + Last + Method:
expr = `exprORMethod(lastLex)`
case Smaller + SwitchCase + Last + Method:
expr = `switchCaseMethod(lastLex)`
case Smaller + GenericIs + Last + Method:
expr = `genericIsMethod(lastLex)`
case Smaller + ExprOR + NoMatch + Method:
expr = `exprORMethod(noMatchLex)`
case Smaller + SwitchCase + NoMatch + Method:
expr = `switchCaseMethod(noMatchLex)`
case Smaller + GenericIs + NoMatch + Method:
expr = `genericIsMethod(noMatchLex)`
case Larger + ExprOR + First + Literal:
expr = fmt.Sprintf(`exprORLarger('%s')`, firstLargeChar)
case Larger + SwitchCase + First + Literal:
expr = fmt.Sprintf(`switchCaseLarger('%s')`, firstLargeChar)
case Larger + GenericIs + First + Literal:
expr = fmt.Sprintf(`genericIsLarger('%s')`, firstLargeChar)
case Larger + ExprOR + Middle + Literal:
expr = fmt.Sprintf(`exprORLarger('%s')`, midLargeChar)
case Larger + SwitchCase + Middle + Literal:
expr = fmt.Sprintf(`switchCaseLarger('%s')`, midLargeChar)
case Larger + GenericIs + Middle + Literal:
expr = fmt.Sprintf(`genericIsLarger('%s')`, midLargeChar)
case Larger + ExprOR + Last + Literal:
expr = fmt.Sprintf(`exprORLarger('%s')`, lastLargeChar)
case Larger + SwitchCase + Last + Literal:
expr = fmt.Sprintf(`switchCaseLarger('%s')`, lastLargeChar)
case Larger + GenericIs + Last + Literal:
expr = fmt.Sprintf(`genericIsLarger('%s')`, lastLargeChar)
case Larger + ExprOR + NoMatch + Literal:
expr = fmt.Sprintf(`exprORLarger('%s')`, noMatchLargeChar)
case Larger + SwitchCase + NoMatch + Literal:
expr = fmt.Sprintf(`switchCaseLarger('%s')`, noMatchLargeChar)
case Larger + GenericIs + NoMatch + Literal:
expr = fmt.Sprintf(`genericIsLarger('%s')`, noMatchLargeChar)
case Larger + ExprOR + First + Const:
expr = `exprORLarger(firstLargeCharConst)`
case Larger + SwitchCase + First + Const:
expr = `switchCaseLarger(firstLargeCharConst)`
case Larger + GenericIs + First + Const:
expr = `genericIsLarger(firstLargeCharConst)`
case Larger + ExprOR + Middle + Const:
expr = `exprORLarger(midLargeCharConst)`
case Larger + SwitchCase + Middle + Const:
expr = `switchCaseLarger(midLargeCharConst)`
case Larger + GenericIs + Middle + Const:
expr = `genericIsLarger(midLargeCharConst)`
case Larger + ExprOR + Last + Const:
expr = `exprORLarger(lastLargeCharConst)`
case Larger + SwitchCase + Last + Const:
expr = `switchCaseLarger(lastLargeCharConst)`
case Larger + GenericIs + Last + Const:
expr = `genericIsLarger(lastLargeCharConst)`
case Larger + ExprOR + NoMatch + Const:
expr = `exprORLarger(noMatchLargeCharConst)`
case Larger + SwitchCase + NoMatch + Const:
expr = `switchCaseLarger(noMatchLargeCharConst)`
case Larger + GenericIs + NoMatch + Const:
expr = `genericIsLarger(noMatchLargeCharConst)`
case Larger + ExprOR + First + Var:
expr = `exprORLarger(firstLargeCharVar)`
case Larger + SwitchCase + First + Var:
expr = `switchCaseLarger(firstLargeCharVar)`
case Larger + GenericIs + First + Var:
expr = `genericIsLarger(firstLargeCharVar)`
case Larger + ExprOR + Middle + Var:
expr = `exprORLarger(midLargeCharVar)`
case Larger + SwitchCase + Middle + Var:
expr = `switchCaseLarger(midLargeCharVar)`
case Larger + GenericIs + Middle + Var:
expr = `genericIsLarger(midLargeCharVar)`
case Larger + ExprOR + Last + Var:
expr = `exprORLarger(lastLargeCharVar)`
case Larger + SwitchCase + Last + Var:
expr = `switchCaseLarger(lastLargeCharVar)`
case Larger + GenericIs + Last + Var:
expr = `genericIsLarger(lastLargeCharVar)`
case Larger + ExprOR + NoMatch + Var:
expr = `exprORLarger(noMatchLargeCharVar)`
case Larger + SwitchCase + NoMatch + Var:
expr = `switchCaseLarger(noMatchLargeCharVar)`
case Larger + GenericIs + NoMatch + Var:
expr = `genericIsLarger(noMatchLargeCharVar)`
case Larger + ExprOR + First + Method:
expr = `exprORMethodLarger(firstLex)`
case Larger + SwitchCase + First + Method:
expr = `switchCaseMethodLarger(firstLex)`
case Larger + GenericIs + First + Method:
expr = `genericIsMethodLarger(firstLex)`
case Larger + ExprOR + Middle + Method:
expr = `exprORMethodLarger(midLex)`
case Larger + SwitchCase + Middle + Method:
expr = `switchCaseMethodLarger(midLex)`
case Larger + GenericIs + Middle + Method:
expr = `genericIsMethodLarger(midLex)`
case Larger + ExprOR + Last + Method:
expr = `exprORMethodLarger(lastLex)`
case Larger + SwitchCase + Last + Method:
expr = `switchCaseMethodLarger(lastLex)`
case Larger + GenericIs + Last + Method:
expr = `genericIsMethodLarger(lastLex)`
case Larger + ExprOR + NoMatch + Method:
expr = `exprORMethodLarger(noMatchLex)`
case Larger + SwitchCase + NoMatch + Method:
expr = `switchCaseMethodLarger(noMatchLex)`
case Larger + GenericIs + NoMatch + Method:
expr = `genericIsMethodLarger(noMatchLex)`
default:
expr = `""`
}
sb.WriteString(fmt.Sprintf("%s_ = %s\n", tabs(depth), expr))
}
var factorNames = [][]string{
{Smaller, Larger},
{ExprOR, SwitchCase, GenericIs},
{First, Middle, Last, NoMatch},
{Literal, Const, Var, Method},
}
const (
RunFormat = `%sb.Run("%s", func(b *testing.B) {%s`
RunFormatClose = `%s})%s`
LoopFormat = `%sfor b.Loop() {%s`
LoopFormatClose = `%s}%s`
)
var tabs = func(n int) string {
return strings.Repeat("\t", n)
}
func GenerateBenchmarkFunc() string {
var sb = strings.Builder{}
sb.WriteString("func BenchmarkValueMembership(b *testing.B) {\n")
GenerateBenchmarkRun(&sb, factorNames[0], 1)
sb.WriteString("}\n")
return sb.String()
}
type Factors []string
func (fs Factors) Has(factors ...string) (ok bool) {
ok = true
for _, factor := range factors {
for _, f := range fs {
if factor != f {
goto end
}
}
}
end:
return ok
}
var benchmarkFactors = make(Factors, len(factorNames))
func GenerateBenchmarkRun(sb *strings.Builder, factors []string, depth int) {
for _, factor := range factors {
sb.WriteString(fmt.Sprintf(RunFormat, tabs(depth), factor, "\n"))
benchmarkFactors[depth-1] = factor
if depth < len(factorNames) {
GenerateBenchmarkRun(sb, factorNames[depth], depth+1)
} else {
sb.WriteString(fmt.Sprintf(LoopFormat, tabs(depth+1), "\n"))
GenerateBenchmark(sb, benchmarkFactors, depth+2)
sb.WriteString(fmt.Sprintf(LoopFormatClose, tabs(depth+1), "\n"))
}
sb.WriteString(fmt.Sprintf(RunFormatClose, tabs(depth), "\n"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment