log/slog: optimize slog Level.String() to avoid fmt.Sprintf

No more overhead of fmt.Sprintf, especially beneficial for
high-frequency logging.

goos: linux
goarch: amd64
pkg: log/slog
cpu: Intel(R) Xeon(R) Gold 6133 CPU @ 2.50GHz
              │ /tmp/old.txt │            /tmp/new.txt             │
              │    sec/op    │   sec/op     vs base                │
LevelString-4   1006.5n ± 2%   334.2n ± 1%  -66.80% (p=0.000 n=10)

              │ /tmp/old.txt │            /tmp/new.txt            │
              │     B/op     │    B/op     vs base                │
LevelString-4     56.00 ± 0%   48.00 ± 0%  -14.29% (p=0.000 n=10)

              │ /tmp/old.txt │          /tmp/new.txt          │
              │  allocs/op   │ allocs/op   vs base            │
LevelString-4     7.000 ± 0%   7.000 ± 0%  ~ (p=1.000 n=10) ¹

Change-Id: I6585d4aaa4da55d72ac70bc66dff45500eccd056
Reviewed-on: https://go-review.googlesource.com/c/go/+/704975
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Auto-Submit: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
mohanson 2025-09-18 11:42:30 +08:00 committed by Gopher Robot
parent b8af744360
commit 8616981ce6
2 changed files with 27 additions and 1 deletions

View file

@ -61,7 +61,11 @@ func (l Level) String() string {
if val == 0 {
return base
}
return fmt.Sprintf("%s%+d", base, val)
sval := strconv.Itoa(int(val))
if val > 0 {
sval = "+" + sval
}
return base + sval
}
switch {

View file

@ -215,3 +215,25 @@ func TestLevelVarString(t *testing.T) {
t.Errorf("got %q, want %q", got, want)
}
}
func BenchmarkLevelString(b *testing.B) {
levels := []Level{
0,
LevelError,
LevelError + 2,
LevelError - 2,
LevelWarn,
LevelWarn - 1,
LevelInfo,
LevelInfo + 1,
LevelInfo - 3,
LevelDebug,
LevelDebug - 2,
}
b.ResetTimer()
for b.Loop() {
for _, level := range levels {
_ = level.String()
}
}
}