lolly/internal/middleware/accesslog/accesslog_bench_test.go
xfy 445401c40f perf(accesslog): add sample_rate for access log to reduce CPU and allocations
Add configurable access log sampling via :
- 0.0-1.0 range; defaults to 1.0 (record all) for backward compatibility
- Uses lock-free atomic counter for deterministic sampling
- Non-2xx responses always logged regardless of sample rate

Benchmark results (combined format, /dev/null):
  Full logging:    ~2245 ns/op, 1987 B/op, 17 allocs/op
  10% sampling:    ~1593 ns/op, 1633 B/op,  6 allocs/op
  Improvement:     -29% latency, -65% allocations/op

This addresses the top application-layer CPU hotspot identified
in the v0.4.0 profile (LogAccess at 16.36% cumulative CPU).
2026-06-11 13:53:41 +08:00

105 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package accesslog 提供访问日志中间件的基准测试。
//
// 该文件测试日志记录的性能开销。
//
// 作者xfy
package accesslog
import (
"testing"
"github.com/valyala/fasthttp"
"rua.plus/lolly/internal/config"
)
// BenchmarkAccessLogProcess 测试访问日志中间件处理性能。
func BenchmarkAccessLogProcess(b *testing.B) {
cfg := &config.LoggingConfig{
Access: config.AccessLogConfig{
Path: "/dev/null",
Format: "combined",
},
}
al := New(cfg)
defer func() { _ = al.Close() }()
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetBodyString("Hello, World!")
}
handler := al.Process(mockHandler)
b.ResetTimer()
for b.Loop() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
ctx.Request.Header.SetHost("example.com")
handler(ctx)
}
}
// BenchmarkAccessLogProcessParallel 测试并发场景下的访问日志性能。
func BenchmarkAccessLogProcessParallel(b *testing.B) {
cfg := &config.LoggingConfig{
Access: config.AccessLogConfig{
Path: "/dev/null",
Format: "combined",
},
}
al := New(cfg)
defer func() { _ = al.Close() }()
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetBodyString("OK")
}
handler := al.Process(mockHandler)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
handler(ctx)
}
})
}
// BenchmarkAccessLogProcessSampled 测试采样模式下的访问日志性能。
//
// 当 sample_rate=0.1 时90% 的成功请求会跳过日志记录,
// 预期性能应显著优于全量记录。
func BenchmarkAccessLogProcessSampled(b *testing.B) {
cfg := &config.LoggingConfig{
Access: config.AccessLogConfig{
Path: "/dev/null",
Format: "combined",
SampleRate: 0.1,
},
}
al := New(cfg)
defer func() { _ = al.Close() }()
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetBodyString("OK")
}
handler := al.Process(mockHandler)
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
handler(ctx)
}
})
}