~bigbes/sr-ht-ecore

b352133b3cfcde8afeb58127bf01d31735faa2fe — Eugene Blikh 2 days ago 54025f4
bearer: silence the std logger the benchmarks were timing

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.
2 files changed, 29 insertions(+), 0 deletions(-)

M .gitignore
M bearer/bearer_bench_test.go
M .gitignore => .gitignore +2 -0
@@ 11,3 11,5 @@
*.db
.beads-credential-key
.beads/proxieddb/
cover.out
bench.txt

M bearer/bearer_bench_test.go => bearer/bearer_bench_test.go +27 -0
@@ 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)