Skip to content

Benchmarks

gogenfilter is designed for linters and static analysis tools where detection overhead must be negligible. The two-phase architecture (filename first, content only when needed) ensures most checks complete with zero I/O.

Benchmarked on Go 1.26, Apple M2. Results may vary by hardware.

Benchmark ns/op B/op allocs/op
Filter (enabled) 307 64 2
Filter (disabled) 5.0 0 0
Filename detection (Phase 1) 14 0 0
Per-generator check (avg) ~15 0 0
MatchPattern (doublestar **) 121 0 0
DetectReason (filename) 648 696 6
DetectReason (content) 1324 744 7
Error construction 3 0 0
errors.Is matching 10 0 0

The primary API. Full end-to-end detection including filesystem access.

Filter/enabled 307 ns/op 64 B/op 2 allocs/op
Filter/disabled 5.0 ns/op 0 B/op 0 allocs/op

A disabled filter is essentially a branch prediction — 5 nanoseconds. An enabled filter with a known-generated file completes in ~307ns with 2 small allocations.

Phase 1: filename-based detection (zero I/O). This is the fast path — a single scan of the filename against the detector table. No file reads, no content parsing.

Filename phase 14 ns/op 0 B/op 0 allocs/op

This benchmarks the internal filename-only check. Results are exact-matched against known generated-file patterns (e.g., models.go, *.sql.go, _templ.go, .pb.go, wire_gen.go, _moq.go, _mock.go, mock_*.go).

Individual Is*Generated functions. Several check both filename patterns and content markers (IsSQLCGenerated, IsTemplGenerated, IsGoEnumGenerated, IsProtobufGenerated, IsMockgenGenerated, IsMockeryGenerated, IsCounterfeiterGenerated, IsGqlgenGenerated, IsEasyjsonGenerated). The rest check content only.

IsGenericGenerated 8.2 ns/op 0 B/op 0 allocs/op
IsSQLCGenerated 23.3 ns/op 0 B/op 0 allocs/op
IsProtobufGenerated 17.4 ns/op 0 B/op 0 allocs/op

All under 25 nanoseconds with zero allocations.

Variadic detection across multiple filter options:

DetectReason/filename_only 648 ns/op 696 B/op 6 allocs/op
DetectReason/content_based 1324 ns/op 744 B/op 7 allocs/op
DetectReason/not_filtered 1031 ns/op 680 B/op 5 allocs/op

Higher cost than the per-generator checks because it iterates all enabled detectors and performs content matching. Still sub-microsecond.

Same as DetectReason but reads from an io.Reader:

DetectReasonReader/sqlc_filename 880 ns/op 1352 B/op 10 allocs/op
DetectReasonReader/not_filtered 1283 ns/op 1272 B/op 9 allocs/op

Includes the cost of reading content from the reader.

MatchPattern with different glob patterns via doublestar:

MatchPattern/question 58 ns/op 0 B/op 0 allocs/op
MatchPattern/exact 78 ns/op 0 B/op 0 allocs/op
MatchPattern/wildcard 113 ns/op 0 B/op 0 allocs/op
MatchPattern/doublestar 121 ns/op 0 B/op 0 allocs/op
MatchPattern/no_match 170 ns/op 0 B/op 0 allocs/op

All zero-allocation. ** globs are the most expensive at ~121ns — still negligible.

Error construction and inspection:

NewSQLCConfigError 2.8 ns/op 0 B/op 0 allocs/op
NewProjectRootError 4.1 ns/op 0 B/op 0 allocs/op
ProjectRootErrorIs 9.3 ns/op 0 B/op 0 allocs/op
SQLCConfigErrorIs 9.9 ns/op 0 B/op 0 allocs/op
ProjectRootErrorError 348 ns/op 144 B/op 3 allocs/op
SQLCConfigErrorError 413 ns/op 176 B/op 5 allocs/op

Error construction and errors.Is matching are essentially free. Error() string formatting allocates but is only called when displaying errors.

Run the benchmarks yourself:

Terminal window
go test -bench=. -benchmem ./...

For stable results, run on a quiet system with CPU frequency scaling disabled.

Historical benchmark trends are tracked automatically on every push to master:

View Live Benchmark Dashboard

The dashboard shows:

  • Time-series charts for all 17 benchmarks
  • Commit-level granularity with tooltips showing commit messages
  • Automatic regression highlighting when performance degrades >150%

Results above are a point-in-time snapshot (Go 1.26, Apple M2). The dashboard provides continuous, hardware-consistent tracking from CI.