perf: avoid string concatenation in loops (#7572)

* perf: avoid string concatenation in loops

Apply perfpsrint linter

Signed-off-by: Philippe Antoine <contact@catenacyber.fr>

* ci: enable perfsprint

Signed-off-by: Philippe Antoine <contact@catenacyber.fr>

---------

Signed-off-by: Philippe Antoine <contact@catenacyber.fr>
This commit is contained in:
Catena cyber
2025-10-06 09:05:58 +02:00
committed by GitHub
parent 51f94b0bb4
commit 625f6c9307
8 changed files with 36 additions and 24 deletions

View File

@@ -15,6 +15,7 @@ linters:
- intrange
- nakedret
- nolintlint
- perfsprint
- prealloc
- protogetter
- staticcheck
@@ -31,10 +32,17 @@ linters:
- common-false-positives
- legacy
- std-error-handling
rules:
# Exclude some linters from running on tests files.
- path: _test\.go
linters:
- perfsprint
settings:
govet:
enable:
- nilness
perfsprint:
error-format: false
revive:
rules:
- name: blank-imports

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"regexp"
"sort"
"strings"
"github.com/coredns/coredns/plugin/pkg/dnsutil"
)
@@ -22,8 +23,6 @@ func checkZoneSyntax(zone string) bool {
// grpc://example.com.:1055
// example.com.:1053 on 127.0.0.1
func startUpZones(protocol, addr string, zones map[string][]*Config) string {
s := ""
keys := make([]string, len(zones))
i := 0
@@ -33,25 +32,26 @@ func startUpZones(protocol, addr string, zones map[string][]*Config) string {
}
sort.Strings(keys)
var sb strings.Builder
for _, zone := range keys {
if !checkZoneSyntax(zone) {
s += fmt.Sprintf("Warning: Domain %q does not follow RFC1035 preferred syntax\n", zone)
sb.WriteString(fmt.Sprintf("Warning: Domain %q does not follow RFC1035 preferred syntax\n", zone))
}
// split addr into protocol, IP and Port
_, ip, port, err := SplitProtocolHostPort(addr)
if err != nil {
// this should not happen, but we need to take care of it anyway
s += fmt.Sprintln(protocol + zone + ":" + addr)
sb.WriteString(fmt.Sprintln(protocol + zone + ":" + addr))
continue
}
if ip == "" {
s += fmt.Sprintln(protocol + zone + ":" + port)
sb.WriteString(fmt.Sprintln(protocol + zone + ":" + port))
continue
}
// if the server is listening on a specific address let's make it visible in the log,
// so one can differentiate between all active listeners
s += fmt.Sprintln(protocol + zone + ":" + port + " on " + ip)
sb.WriteString(fmt.Sprintln(protocol + zone + ":" + port + " on " + ip))
}
return s
return sb.String()
}

View File

@@ -1,5 +1,9 @@
package auto
import (
"strings"
)
// rewriteToExpand rewrites our template string to one that we can give to regexp.ExpandString. This basically
// involves prefixing any '{' with a '$'.
func rewriteToExpand(s string) string {
@@ -7,14 +11,13 @@ func rewriteToExpand(s string) string {
// Also wasteful as we build the string with +=. This is OKish
// as we do this during config parsing.
copy := ""
var copySb strings.Builder
for _, c := range s {
if c == '{' {
copy += "$"
copySb.WriteString("$")
}
copy += string(c)
copySb.WriteString(string(c))
}
return copy
return copySb.String()
}

View File

@@ -29,7 +29,7 @@ func NewRequest(method, url string, m *dns.Msg) (*http.Request, error) {
}
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = fmt.Sprintf("https://%s", url)
url = "https://" + url
}
switch method {

View File

@@ -171,14 +171,14 @@ const escapeSeq = "\\"
// `\\052.example.com.` -> `*.example.com`
// `\\137.example.com.` -> error ('_' is not valid)
func maybeUnescape(s string) (string, error) {
var out string
var outSb strings.Builder
for {
i := strings.Index(s, escapeSeq)
if i < 0 {
return out + s, nil
return outSb.String() + s, nil
}
out += s[:i]
outSb.WriteString(s[:i])
li, ri := i+len(escapeSeq), i+len(escapeSeq)+3
if ri > len(s) {
@@ -196,7 +196,7 @@ func maybeUnescape(s string) (string, error) {
case r >= rune('a') && r <= rune('z'): // Route53 converts everything to lowercase.
case r >= rune('0') && r <= rune('9'):
case r == rune('*'):
if out != "" {
if outSb.Len() != 0 {
return "", errors.New("`*' only supported as wildcard (leftmost label)")
}
case r == rune('-'):
@@ -205,7 +205,7 @@ func maybeUnescape(s string) (string, error) {
return "", fmt.Errorf("invalid character: %s%#03o", escapeSeq, r)
}
out += string(r)
outSb.WriteString(string(r))
s = s[i+len(escapeSeq)+3:]
}

View File

@@ -127,7 +127,7 @@ func setup(c *caddy.Controller) error {
refreshStr := c.Val()
_, err := strconv.Atoi(refreshStr)
if err == nil {
refreshStr = fmt.Sprintf("%ss", c.Val())
refreshStr = c.Val() + "s"
}
refresh, err = time.ParseDuration(refreshStr)
if err != nil {

View File

@@ -111,9 +111,10 @@ func keyTag(ps []Pair) string {
if len(ps) == 0 {
return ""
}
s := ""
var sb strings.Builder
for _, p := range ps {
s += strconv.Itoa(int(p.KeyTag)) + ","
sb.WriteString(strconv.Itoa(int(p.KeyTag)) + ",")
}
s := sb.String()
return s[:len(s)-1]
}

View File

@@ -157,14 +157,14 @@ func newMetricFamily(dtoMF *dto.MetricFamily) *MetricFamily {
mf.Metrics[i] = summary{
Labels: makeLabels(m),
Quantiles: makeQuantiles(m),
Count: fmt.Sprint(m.GetSummary().GetSampleCount()),
Count: strconv.FormatUint(m.GetSummary().GetSampleCount(), 10),
Sum: fmt.Sprint(m.GetSummary().GetSampleSum()),
}
} else if dtoMF.GetType() == dto.MetricType_HISTOGRAM {
mf.Metrics[i] = histogram{
Labels: makeLabels(m),
Buckets: makeBuckets(m),
Count: fmt.Sprint(m.GetHistogram().GetSampleCount()),
Count: strconv.FormatUint(m.GetHistogram().GetSampleCount(), 10),
Sum: fmt.Sprint(m.GetSummary().GetSampleSum()),
}
} else {
@@ -209,7 +209,7 @@ func makeQuantiles(m *dto.Metric) map[string]string {
func makeBuckets(m *dto.Metric) map[string]string {
result := map[string]string{}
for _, b := range m.GetHistogram().GetBucket() {
result[fmt.Sprint(b.GetUpperBound())] = fmt.Sprint(b.GetCumulativeCount())
result[fmt.Sprint(b.GetUpperBound())] = strconv.FormatUint(b.GetCumulativeCount(), 10)
}
return result
}