From b352133b3cfcde8afeb58127bf01d31735faa2fe Mon Sep 17 00:00:00 2001 From: Eugene Blikh Date: Sun, 16 Aug 2026 07:56:07 +0300 Subject: [PATCH] bearer: silence the std logger the benchmarks were timing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sr-ht-core's auth.DecodeBearerToken calls log.Printf on every token it refuses, so BenchmarkValidate/invalid wrote one line per iteration. The cost was not the file: log.Printf takes a mutex, and the case reported 925 ns/op where the work is 92.5. The file was a hazard too. An unfiltered run of this package produced 9.5 million lines and 901 MB, and benchfmt skips what it cannot parse — so bench.sr.ht would have accepted that upload and reported success over it. Ignore cover.out and bench.txt: make cover and make bench write them into the checkout. --- .gitignore | 2 ++ bearer/bearer_bench_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/.gitignore b/.gitignore index 673cd2135443792323ed326f3dd5dfeec97a6624..c7b4858b6bdc96131fd0a6974e605980cc131bb4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ *.db .beads-credential-key .beads/proxieddb/ +cover.out +bench.txt diff --git a/bearer/bearer_bench_test.go b/bearer/bearer_bench_test.go index d5c9915f36e95259699f7a7bd074e6c58ba76ecb..18c3249b72f6831b948c8233094ad31a24f67936 100644 --- a/bearer/bearer_bench_test.go +++ b/bearer/bearer_bench_test.go @@ -3,11 +3,32 @@ package bearer import ( "context" "errors" + "io" + "log" "net/http" "net/http/httptest" "testing" ) +// discardStdLog silences the standard logger for one benchmark. sr-ht-core's +// auth.DecodeBearerToken calls log.Printf on every token it refuses, so the +// invalid case below writes one line per iteration — an unfiltered run of this +// package produced 9.5 million of them and a 901 MB file. Two things follow. +// The number stops being a measurement of this package: log.Printf takes a +// mutex, so what was timed was the logger. And the file is worse than useless +// rather than merely large, because benchfmt skips lines it cannot parse, so +// bench.sr.ht would accept that upload and report success over it. +// +// It is the std log package here rather than slog — that is why this is not +// the discardLog the middleware and chimw benchmarks share. +func discardStdLog(b *testing.B) { + b.Helper() + + previous := log.Writer() + log.SetOutput(io.Discard) + b.Cleanup(func() { log.SetOutput(previous) }) +} + // The grant strings these benchmarks present. The stateless one is what a short // token carries; the registered one adds the id: member that turns step 4 from // a no-op into a cache lookup. @@ -74,6 +95,8 @@ func benchValidator(b *testing.B) *Validator { // the path an instance under a flood of forged credentials runs; it must // stay the cheapest thing here. func BenchmarkValidate(b *testing.B) { + discardStdLog(b) + ctx := context.Background() v := benchValidator(b) @@ -136,6 +159,8 @@ func BenchmarkValidate(b *testing.B) { // beside BenchmarkValidate/stateless — the gap is the grant check that Inspect // leaves to the handler. func BenchmarkInspect(b *testing.B) { + discardStdLog(b) + ctx := context.Background() v := benchValidator(b) presented := ourToken(benchGrants) @@ -158,6 +183,8 @@ func BenchmarkInspect(b *testing.B) { // is not, and the point of measuring it is to know which of the two dominates // before somebody proposes sharding the cache. func BenchmarkValidateParallel(b *testing.B) { + discardStdLog(b) + ctx := context.Background() v := benchValidator(b) registered := ourToken(benchGrantsRegistered)