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