Skip to content

Instantly share code, notes, and snippets.

@thockin
Last active November 7, 2021 20:16
Show Gist options
  • Save thockin/8fc599cc4adc7aba72a367057704a798 to your computer and use it in GitHub Desktop.
Save thockin/8fc599cc4adc7aba72a367057704a798 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"testing"
)
//
// Baseline perf for single operations
//
func BenchmarkOneAppend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
write(buf, append(a, "these", "are")...)
if buf.String() != "a few of my favorite things these are" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneVariadic(b *testing.B) {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
for i := 0; i < b.N; i++ {
buf.Reset()
write(buf, "these", "are", "a", "few", "of", "my", "favorite", "things")
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOnePrepend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
write(buf, prepend(a, "these", "are")...)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneSG(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
writeSG(buf, []string{"these", "are"}, a)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneIntf(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
writeIntf(buf, "these", "are", a)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
//
// More representative patterns. Each of these should illustrate how c9ode
// looks for:
// * inline args (all specified in one place)
// * accumulated args, where the chain is known up-front
// * accumulated args, where the chain is known at the end
//
func BenchmarkReprSGMinSlices(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeSG(buf, []string{
"-A", "CHAIN",
"-m", protocol, "-p", protocol,
"-d", ip, "--dport", port,
"-j", "FOOBAR",
})
// Accumulate args, chain is known.
a = append(a[:0], "-A", "CHAIN")
a = append(a, "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeSG(buf, a)
// Accumulate args, chain is late-bound.
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeSG(buf, []string{"-A", "CHAIN"}, a)
}
}
func BenchmarkReprSGMinSlicesHelpers(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
// NB: We can't unpack these slices
writeSG(buf,
appendFunc("CHAIN"),
protocolFunc(protocol),
destFunc(ip, port),
jumpFunc("FOOBAR"),
)
// Accumulate args, chain is known.
a = append(a[:0], appendFunc("CHAIN")...)
a = append(a, protocolFunc(protocol)...)
a = append(a, destFunc(ip, port)...)
a = append(a, jumpFunc("FOOBAR")...)
writeSG(buf, a)
// Accumulate args, chain is late-bound.
a = append(a[:0], protocolFunc(protocol)...)
a = append(a, destFunc(ip, port)...)
a = append(a, jumpFunc("FOOBAR")...)
writeSG(buf, appendFunc("CHAIN"), a)
}
}
func BenchmarkReprSGManySlices(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeSG(buf,
[]string{"-A", "CHAIN"},
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"},
)
// Accumulate args, chain is known.
a = append(a[:0], []string{"-A", "CHAIN"})
a = append(a, []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
writeSG(buf, a...)
// Accumulate args, chain is late-bound.
a = append(a[:0], []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
writeSG(buf, append([][]string{{"-A", "CHAIN"}}, a...)...)
}
}
func BenchmarkReprSGManySlicesHelpers(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeSG(buf,
appendFunc("CHAIN"),
protocolFunc(protocol),
destFunc(ip, port),
jumpFunc("FOOBAR"),
)
// Accumulate args, chain is known.
a = append(a[:0], appendFunc("CHAIN"))
a = append(a, protocolFunc(protocol))
a = append(a, destFunc(ip, port))
a = append(a, jumpFunc("FOOBAR"))
writeSG(buf, a...)
// Accumulate args, chain is late-bound.
a = append(a[:0], protocolFunc(protocol))
a = append(a, destFunc(ip, port))
a = append(a, jumpFunc("FOOBAR"))
writeSG(buf, append([][]string{{"-A", "CHAIN"}}, a...)...)
}
}
func BenchmarkReprIntfMinSlices(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeIntf(buf,
"-A", "CHAIN",
"-m", protocol, "-p", protocol,
"-d", ip, "--dport", port,
"-j", "FOOBAR",
)
// Accumulate args, chain is known.
a = append(a[:0], "-A", "CHAIN")
a = append(a, "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeIntf(buf, a)
// Accumulate args, chain is late-bound.
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeIntf(buf, "-A", "CHAIN", a)
}
}
func BenchmarkReprIntfMinSlicesHelpers(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
// NB: We can't unpack these slices
writeIntf(buf,
appendFunc("CHAIN"),
protocolFunc(protocol),
destFunc(ip, port),
jumpFunc("FOOBAR"),
)
// Accumulate args, chain is known.
a = append(a[:0], appendFunc("CHAIN")...)
a = append(a, protocolFunc(protocol)...)
a = append(a, destFunc(ip, port)...)
a = append(a, jumpFunc("FOOBAR")...)
writeIntf(buf, a)
// Accumulate args, chain is late-bound.
a = append(a[:0], protocolFunc(protocol)...)
a = append(a, destFunc(ip, port)...)
a = append(a, jumpFunc("FOOBAR")...)
writeIntf(buf, appendFunc("CHAIN"), a)
}
}
func BenchmarkReprIntfManySlices(b *testing.B) {
a := make([]interface{}, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeIntf(buf,
[]string{"-A", "CHAIN"},
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"},
)
// Accumulate args, chain is known.
a = append(a[:0], []string{"-A", "CHAIN"})
a = append(a, []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
writeIntf(buf, a...)
// Accumulate args, chain is late-bound.
a = append(a[:0], []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
writeIntf(buf, append([]interface{}{"-A", "CHAIN"}, a...)...)
}
}
func BenchmarkReprIntfManySlicesHelpers(b *testing.B) {
a := make([]interface{}, 0, 64)
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
// Inline args.
writeIntf(buf,
appendFunc("CHAIN"),
protocolFunc(protocol),
destFunc(ip, port),
jumpFunc("FOOBAR"),
)
// Accumulate args, chain is known.
a = append(a[:0], appendFunc("CHAIN"))
a = append(a, protocolFunc(protocol))
a = append(a, destFunc(ip, port))
a = append(a, jumpFunc("FOOBAR"))
writeIntf(buf, a...)
// Accumulate a series of slices (e.g. via helper functions)
a = append(a[:0], protocolFunc(protocol))
a = append(a, destFunc(ip, port))
a = append(a, jumpFunc("FOOBAR"))
writeIntf(buf, append([]interface{}{"-A", "CHAIN"}, a...)...)
}
}
func BenchmarkIntf(b *testing.B) {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeIntf(buf,
"-A", "CHAIN",
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"})
}
}
func BenchmarkIntf2(b *testing.B) {
buf := bytes.NewBuffer(make([]byte, 0, 1024))
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeIntf2(buf,
"-A", "CHAIN",
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"})
}
}
// go:noinline
func appendFunc(chain string) []string {
return []string{"-A", chain}
}
// go:noinline
func protocolFunc(proto string) []string {
return []string{"-m", proto, "-p", proto}
}
// go:noinline
func destFunc(ip, port string) []string {
return []string{"-d", ip, "--dport", port}
}
// go:noinline
func jumpFunc(chain string) []string {
return []string{"-j", chain}
}
// other code used in the above
func prepend(sl []string, args ...string) []string {
return append(args, sl...)
}
// go:noinline
func write(buf *bytes.Buffer, words ...string) {
for i, w := range words {
if i > 0 {
buf.WriteByte(' ')
}
buf.WriteString(w)
}
}
// go:noinline
func writeSG(buf *bytes.Buffer, phrases ...[]string) {
for i, p := range phrases {
if i > 0 {
buf.WriteByte(' ')
}
write(buf, p...)
}
}
// go:noinline
func writeIntf(buf *bytes.Buffer, parts ...interface{}) {
for i, p := range parts {
if i > 0 {
buf.WriteByte(' ')
}
switch x := p.(type) {
case string:
buf.WriteString(x)
case []string:
write(buf, x...)
default:
panic("huh?")
}
}
}
// go:noinline
func writeIntf2(buf *bytes.Buffer, parts ...interface{}) {
for i, p := range parts {
if i > 0 {
buf.WriteByte(' ')
}
switch x := p.(type) {
case string:
buf.WriteString(x)
case []string:
for i, p := range x {
if i > 0 {
buf.WriteByte(' ')
}
buf.WriteString(p)
}
default:
panic("huh?")
}
}
}
package main
import (
"bytes"
"testing"
)
//
// Baseline perf for single operations
//
func BenchmarkOneAppend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
write(&buf, append(a, "these", "are")...)
if buf.String() != "a few of my favorite things these are" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneVariadic(b *testing.B) {
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
write(&buf, "these", "are", "a", "few", "of", "my", "favorite", "things")
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOnePrepend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
write(&buf, prepend(a, "these", "are")...)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOnePrependInPlace(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
write(&buf, prependInPlaceCopy(a, "these", "are")...)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneSG(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
writeSG(&buf, []string{"these", "are"}, a)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
func BenchmarkOneIntf(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
writeIntf(&buf, "these", "are", a)
if buf.String() != "these are a few of my favorite things" {
b.Fatalf("bad result: %q", buf.String())
}
}
}
//
// Various ideas for models, artificial usage
//
// Doesn't satisfy requirements, but sets the perf bar.
func BenchmarkAppend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
for j := 0; j < 16; j++ {
a = append(a, "these", "are")
}
write(&buf, a...)
//if buf.String() != "a few of my favorite things these are" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
func BenchmarkPrepend(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
for j := 0; j < 16; j++ {
a = prepend(a, "these", "are")
}
write(&buf, a...)
//if buf.String() != "these are a few of my favorite things" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
func BenchmarkPrependInPlaceManual(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
for j := 0; j < 16; j++ {
a = prependInPlace(a, "these", "are")
}
write(&buf, a...)
//if buf.String() != "these are a few of my favorite things" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
func BenchmarkPrependInPlaceCopy(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "a", "few", "of", "my", "favorite", "things")
for j := 0; j < 16; j++ {
a = prependInPlaceCopy(a, "these", "are")
}
write(&buf, a...)
//if buf.String() != "these are a few of my favorite things" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
func BenchmarkScatterGatherFlat(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], []string{"a", "few", "of", "my", "favorite", "things"})
for j := 0; j < 16; j++ {
a = prependSG(a, "these", "are")
}
writeSG(&buf, a...)
//if buf.String() != "these are a few of my favorite things" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
type Phrase struct {
before []string
after *Phrase
}
func BenchmarkScatterGatherDeep(b *testing.B) {
buf := bytes.Buffer{}
for i := 0; i < b.N; i++ {
buf.Reset()
a := Phrase{before: []string{"a", "few", "of", "my", "favorite", "things"}}
for j := 0; j < 16; j++ {
a = prependSGDeep(a, "these", "are")
}
writeSGDeep(&buf, a)
//if buf.String() != "these are a few of my favorite things" {
//b.Fatalf("bad result: %q", buf.String())
//}
}
}
//
// More representative patterns
//
func BenchmarkReprSGAsFewAsPossible(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeSG(&buf, []string{"-A", "CHAIN"}, a)
}
}
func BenchmarkReprSGMany(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
// Can't do writeSG(&buf, []string{"-A", "CHAIN"}, a...) -- go won't let us
writeSG(&buf, append([][]string{{"-A", "CHAIN"}}, a...)...)
}
}
func BenchmarkReprSGManyInline(b *testing.B) {
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeSG(&buf,
[]string{"-A", "CHAIN"},
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"})
}
}
func BenchmarkReprIntfAsFewAsPossible(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeIntf(&buf, "-A", "CHAIN", a)
}
}
func BenchmarkReprIntfMany(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], []string{"-m", protocol, "-p", protocol})
a = append(a, []string{"-d", ip, "--dport", port})
a = append(a, []string{"-j", "FOOBAR"})
// Can't do writeIntf(&buf, "-A", "CHAIN", a...)
// Can't do writeIntf(&buf, append([][]string{{"-A", "CHAIN"}}, a...)...)
s := []interface{}{"-A", "CHAIN"}
for _, x := range a {
s = append(s, x)
}
writeIntf(&buf, s...)
}
}
func BenchmarkReprIntfManyInline(b *testing.B) {
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeIntf(&buf,
"-A", "CHAIN",
[]string{"-m", protocol, "-p", protocol},
[]string{"-d", ip, "--dport", port},
[]string{"-j", "FOOBAR"})
}
}
func BenchmarkReprClauseAsFewAsPossible(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeClause(&buf, appendClause("CHAIN"), argsClause(a))
}
}
func BenchmarkReprClauseMany(b *testing.B) {
a := make([]clause, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], protocolClause(protocol))
a = append(a, destClause(ip, port))
a = append(a, jumpClause("FOOBAR"))
// Can't do writeClause(&buf, appendClause("CHAIN"), a...)
writeClause(&buf, appendClause("CHAIN"), metaClause(a...))
}
}
func BenchmarkReprClauseManyInline(b *testing.B) {
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeClause(&buf,
appendClause("CHAIN"),
protocolClause(protocol),
destClause(ip, port),
jumpClause("FOOBAR"))
}
}
type clause func(buf *bytes.Buffer)
func appendClause(chain string) clause {
return func(buf *bytes.Buffer) {
write(buf, "-A", chain)
}
}
func protocolClause(proto string) clause {
return func(buf *bytes.Buffer) {
write(buf, "-m", proto, "-p", proto)
}
}
func destClause(ip, port string) clause {
return func(buf *bytes.Buffer) {
write(buf, "-d", ip, "--dport", port)
}
}
func jumpClause(chain string) clause {
return func(buf *bytes.Buffer) {
write(buf, "-j", chain)
}
}
func argsClause(args []string) clause {
return func(buf *bytes.Buffer) {
write(buf, args...)
}
}
func metaClause(clauses ...clause) clause {
return func(buf *bytes.Buffer) {
for _, c := range clauses {
c(buf)
}
}
}
func BenchmarkReprFuncAsFewAsPossible(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], "-m", protocol, "-p", protocol)
a = append(a, "-d", ip, "--dport", port)
a = append(a, "-j", "FOOBAR")
writeFunc(&buf, appendFunc("CHAIN"), a)
}
}
func BenchmarkReprFuncAsFewAsPossible2(b *testing.B) {
a := make([]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], protocolFunc(protocol)...)
a = append(a, destFunc(ip, port)...)
a = append(a, jumpFunc("FOOBAR")...)
writeFunc(&buf, appendFunc("CHAIN"), a)
}
}
func BenchmarkReprFuncMany(b *testing.B) {
a := make([][]string, 0, 64)
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
a = append(a[:0], protocolFunc(protocol))
a = append(a, destFunc(ip, port))
a = append(a, jumpFunc("FOOBAR"))
writeFunc(&buf, appendFunc("CHAIN"), a)
}
}
func BenchmarkReprFuncManyInline(b *testing.B) {
buf := bytes.Buffer{}
protocol := "tcp"
port := "1234"
ip := "1.2.3.4"
for i := 0; i < b.N; i++ {
buf.Reset()
writeFunc(&buf,
appendFunc("CHAIN"),
protocolFunc(protocol),
destFunc(ip, port),
jumpFunc("FOOBAR"))
}
}
func appendFunc(chain string) []string {
return []string{"-A", chain}
}
func protocolFunc(proto string) []string {
return []string{"-m", proto, "-p", proto}
}
func destFunc(ip, port string) []string {
return []string{"-d", ip, "--dport", port}
}
func jumpFunc(chain string) []string {
return []string{"-j", chain}
}
// other code used in the above
func prepend(sl []string, args ...string) []string {
return append(args, sl...)
}
func prependInPlace(sl []string, args ...string) []string {
toShift := len(sl)
toInsert := len(args)
sl = append(sl, args...)
for i := toShift - 1; i >= 0; i-- {
sl[i+toInsert] = sl[i]
}
for i, w := range args {
sl[i] = w
}
return sl
}
func prependInPlaceCopy(sl []string, args ...string) []string {
toInsert := len(args)
sl = append(sl, args...)
copy(sl[toInsert:], sl)
copy(sl[:toInsert], args)
return sl
}
func prependSG(sl [][]string, args ...string) [][]string {
sl = append(sl, args)
copy(sl[1:], sl)
sl[0] = args
return sl
}
func prependSGDeep(p Phrase, args ...string) Phrase {
return Phrase{
before: args,
after: &p,
}
}
// go:noinline
func write(buf *bytes.Buffer, words ...string) {
for i, w := range words {
if i > 0 {
buf.WriteByte(' ')
}
buf.WriteString(w)
}
}
// go:noinline
func writeSG(buf *bytes.Buffer, phrases ...[]string) {
for i, p := range phrases {
if i > 0 {
buf.WriteByte(' ')
}
write(buf, p...)
}
}
// go:noinline
func writeSGDeep(buf *bytes.Buffer, p Phrase) {
write(buf, p.before...)
if p.after != nil {
buf.WriteByte(' ')
writeSGDeep(buf, *p.after)
}
}
// go:noinline
func writeIntf(buf *bytes.Buffer, parts ...interface{}) {
for i, p := range parts {
if i > 0 {
buf.WriteByte(' ')
}
switch x := p.(type) {
case string:
buf.WriteString(x)
case []string:
write(buf, x...)
default:
panic("huh?")
}
}
}
// go:noinline
func writeClause(buf *bytes.Buffer, clauses ...clause) {
for i, c := range clauses {
if i > 0 {
buf.WriteByte(' ')
}
c(buf)
}
}
// go:noinline
func writeFunc(buf *bytes.Buffer, parts ...interface{}) {
for i, p := range parts {
if i > 0 {
buf.WriteByte(' ')
}
switch x := p.(type) {
case string:
buf.WriteString(x)
case []string:
write(buf, x...)
case [][]string:
writeSG(buf, x...)
default:
panic("huh?")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment