Last active
March 19, 2025 12:09
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
}) | |
}) | |
}) | |
}) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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