Hot Path
tzOffsetString in libbeat/common/dtfmt/fields.go:147-170 is on the local-time JSON encoding path (libbeat/outputs/codec/json/json_bench_test.go:46-58). The current implementation allocates on every call by building []byte and converting it to string.
Profiling Data
Before:
$ go test -run '^$' -bench '^BenchmarkLocalTime$' -benchmem -count=8 ./libbeat/outputs/codec/json
BenchmarkLocalTime-4 1274766 954.9 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1266380 951.5 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1258628 949.9 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1272968 948.1 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1234520 950.9 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1254757 953.1 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1234729 942.6 ns/op 104 B/op 2 allocs/op
BenchmarkLocalTime-4 1256445 954.2 ns/op 104 B/op 2 allocs/op
Proposed Change
Precompute +HH:MM / -HH:MM timezone strings once in a static lookup table and reuse them at runtime:
--- a/libbeat/common/dtfmt/fields.go
+++ b/libbeat/common/dtfmt/fields.go
@@
+const (
+ tzOffsetMinMinutes = -24 * 60
+ tzOffsetMaxMinutes = 24 * 60
+)
+
+var tzOffsetStrings = buildTZOffsetStrings()
+
func tzOffsetString(ctx *ctx) (string, error) {
tzOffsetMinutes := ctx.tzOffset / 60
+ if tzOffsetMinutes >= tzOffsetMinMinutes && tzOffsetMinutes <= tzOffsetMaxMinutes {
+ return tzOffsetStrings[tzOffsetMinutes-tzOffsetMinMinutes], nil
+ }
+ return formatTZOffset(tzOffsetMinutes), nil
}
formatTZOffset retains existing formatting semantics for fallback/out-of-range values.
Results
After:
$ go test -run '^$' -bench '^BenchmarkLocalTime$' -benchmem -count=8 ./libbeat/outputs/codec/json
BenchmarkLocalTime-4 1342268 917.2 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1324545 914.9 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1337199 907.8 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1337120 905.7 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1335277 903.6 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1312209 898.6 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1342334 913.2 ns/op 96 B/op 1 allocs/op
BenchmarkLocalTime-4 1333272 916.7 ns/op 96 B/op 1 allocs/op
Improvement:
- ~4.3% faster (
~950.6 ns/op → ~909.7 ns/op)
- 7.7% lower bytes allocated (
104 B/op → 96 B/op)
- 50% fewer allocations (
2 allocs/op → 1 alloc/op)
Verification
go test ./libbeat/common/dtfmt
go test ./libbeat/outputs/codec/json
- Added coverage for offset formatting edge cases in
libbeat/common/dtfmt/dtfmt_test.go:177-197
Evidence
- Commands run:
go test -run '^$' -bench '^BenchmarkLocalTime$' -benchmem -count=8 ./libbeat/outputs/codec/json (before/after, same command)
go test ./libbeat/common/dtfmt
go test ./libbeat/outputs/codec/json
- Code references:
- Current hot path:
libbeat/common/dtfmt/fields.go:147-170
- Benchmark:
libbeat/outputs/codec/json/json_bench_test.go:46-58
- Behavior tests:
libbeat/common/dtfmt/dtfmt_test.go:177-197
Duplicate check: /tmp/previous-findings.json has no open issue for dtfmt.tzOffsetString / BenchmarkLocalTime (closest closed item is about add_locale, not this path).
What is this? | From workflow: Performance Profiler
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
Hot Path
tzOffsetStringinlibbeat/common/dtfmt/fields.go:147-170is on the local-time JSON encoding path (libbeat/outputs/codec/json/json_bench_test.go:46-58). The current implementation allocates on every call by building[]byteand converting it tostring.Profiling Data
Before:
Proposed Change
Precompute
+HH:MM/-HH:MMtimezone strings once in a static lookup table and reuse them at runtime:formatTZOffsetretains existing formatting semantics for fallback/out-of-range values.Results
After:
Improvement:
~950.6 ns/op→~909.7 ns/op)104 B/op→96 B/op)2 allocs/op→1 alloc/op)Verification
go test ./libbeat/common/dtfmtgo test ./libbeat/outputs/codec/jsonlibbeat/common/dtfmt/dtfmt_test.go:177-197Evidence
go test -run '^$' -bench '^BenchmarkLocalTime$' -benchmem -count=8 ./libbeat/outputs/codec/json(before/after, same command)go test ./libbeat/common/dtfmtgo test ./libbeat/outputs/codec/jsonlibbeat/common/dtfmt/fields.go:147-170libbeat/outputs/codec/json/json_bench_test.go:46-58libbeat/common/dtfmt/dtfmt_test.go:177-197Duplicate check:
/tmp/previous-findings.jsonhas no open issue fordtfmt.tzOffsetString/BenchmarkLocalTime(closest closed item is aboutadd_locale, not this path).What is this? | From workflow: Performance Profiler
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.