refactor: use strings.Builder to improve performance#7364
refactor: use strings.Builder to improve performance#7364francislavoie merged 2 commits intocaddyserver:masterfrom
Conversation
|
Interested to see any tests showing how much the performance gain is, if any, in ns per request or requests per second. |
|
@vnxme I wrote a benchmark that shows the performance advantage of using package caddy_test
import (
"fmt"
"strings"
"testing"
)
type Route struct {
Group string
MatcherSetsRaw string
HandlersRaw []string
Terminal bool
}
func (r Route) StringOld() string {
handlersRaw := "["
for _, hr := range r.HandlersRaw {
handlersRaw += " " + string(hr)
}
handlersRaw += "]"
return fmt.Sprintf(`{Group:"%s" MatcherSetsRaw:%s HandlersRaw:%s Terminal:%t}`,
r.Group, r.MatcherSetsRaw, handlersRaw, r.Terminal)
}
func (r Route) StringNew() string {
var handlersRaw strings.Builder
handlersRaw.WriteString("[")
for _, hr := range r.HandlersRaw {
handlersRaw.WriteString(" " + string(hr))
}
handlersRaw.WriteString("]")
return fmt.Sprintf(`{Group:"%s" MatcherSetsRaw:%s HandlersRaw:%s Terminal:%t}`,
r.Group, r.MatcherSetsRaw, handlersRaw.String(), r.Terminal)
}
func BenchmarkRouteString_Old(b *testing.B) {
r := Route{
Group: "api",
MatcherSetsRaw: "[matcher]",
HandlersRaw: []string{"foo", "bar", "baz", "qux", "quux"},
Terminal: true,
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = r.StringOld()
}
}
func BenchmarkRouteString_New(b *testing.B) {
r := Route{
Group: "api",
MatcherSetsRaw: "[matcher]",
HandlersRaw: []string{"foo", "bar", "baz", "qux", "quux"},
Terminal: true,
}
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = r.StringNew()
}
}➜ benchmark go test -bench=. -benchmem
goos: darwin
goarch: arm64
pkg: demo/stringsbuilder/benchmark
cpu: Apple M4
BenchmarkRouteString_Old-10 5239779 211.3 ns/op 248 B/op 10 allocs/op
BenchmarkRouteString_New-10 6258066 193.5 ns/op 200 B/op 7 allocs/op
PASS
ok demo/stringsbuilder/benchmark 3.482s
|
|
@zjumathcode Thanks, so you have an 8% gain in ns/op, a 19% decrease in B/op and a 30% drop in allocs/op in your benchmark which is quite good. Does your PR cover all the places in the code where strings are concatenated? |
This is a generic performance improvement plan, based on suggestions and support from the Go team. More info: golang/go#75190. |
269d616 to
6f33bf1
Compare
Signed-off-by: zjumathcode <pai314159@2980.com>
…ites) also revert builder change in client_test.go refactor(logging): build IP mask output via join of parts (more efficient)
6f33bf1 to
fd4c733
Compare
|
The PR had fallen inactive so I went ahead and fixed up the remainder as per review comments. |
Assistance Disclosure
strings.Builder has fewer memory allocations and better performance.
More info: golang/go#75190