From c8949055ed181e0bf61789c29a74471575b978ac Mon Sep 17 00:00:00 2001 From: "M. J. Fromberger" Date: Fri, 30 Aug 2024 08:17:29 -0700 Subject: [PATCH] shell: reduce allocations in Quote MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grow the quote buffer to a plausible baseline before filling. Add BenchmarkQuote. Quote-10 │ before.txt │ after.txt | vs base │ sec/op │ sec/op | | 778.1µ | 801.0µ | +2.95% │ B/op │ B/op | | 711.9Ki | 512.0Ki | -28.08% │ allocs/op │ allocs/op | | 14.000 | 3.000 | -78.57% --- shell/bench_test.go | 28 ++++++++++++++++++++++++++++ shell/shell.go | 1 + 2 files changed, 29 insertions(+) diff --git a/shell/bench_test.go b/shell/bench_test.go index 6d2b875..b0a1357 100644 --- a/shell/bench_test.go +++ b/shell/bench_test.go @@ -76,4 +76,32 @@ func BenchmarkSplit(b *testing.B) { } } +func BenchmarkQuote(b *testing.B) { + const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789 \t\n\n\n" + src := rand.NewSource(67890) + r := rand.New(src) + + var buf bytes.Buffer + for range 100000 { + switch v := r.Float64(); { + case v < 0.5: + buf.WriteByte('\'') + case v < 0.1: + buf.WriteByte('"') + case v < 0.15: + buf.WriteByte('\\') + default: + pos := math.Ceil(r.Float64()*float64(len(alphabet))) - 1 + buf.WriteByte(alphabet[int(pos)]) + } + } + + input := buf.String() + b.ResetTimer() + + for range b.N { + shell.Quote(input) + } +} + func ignore(string) bool { return true } diff --git a/shell/shell.go b/shell/shell.go index efea462..396eba9 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -292,6 +292,7 @@ func quote(s string, buf *bytes.Buffer) string { } buf.Reset() + buf.Grow(len(s)) inq := false for i := range len(s) { ch := s[i]