regex-bench

August 5, 2026 · View on GitHub

Cross-language regex benchmark for real-world patterns.

Created to provide data for golang/go#26623 discussion on Go regex performance.

Test Environment

All benchmarks run on identical conditions:

  • OS: Linux (Ubuntu via WSL2 or GitHub Actions)
  • Input: 6.0 MB generated text file
  • Method: Each engine compiled natively, same input file, same patterns

Note: Cross-compiled Go binaries run in WSL2 for fair comparison with Rust.

Results (v0.12.23)

GitHub Actions Ubuntu (AMD EPYC), 6.0 MB input (using FindAll for fair comparison)

PatternGo stdlibGo coregexRust regexvs stdlibvs RustWinner
inner_literal232 ms0.26 ms13.55 ms893x52x fastercoregex
ip489 ms0.77 ms13.53 ms635x17.6x fastercoregex
email257 ms0.55 ms0.26 ms467x2.1x slowerRust
uri258 ms0.61 ms0.34 ms424x1.8x slowerRust
multiline_php101 ms0.38 ms0.76 ms266x2.0x fastercoregex
version163 ms0.65 ms0.79 ms250x1.2x fastercoregex
suffix236 ms1.79 ms13.70 ms132x7.7x fastercoregex
literal_alt232 ms4.69 ms0.63 ms49x7.4x slowerRust
http_methods103 ms1.51 ms0.64 ms68x2.4x slowerRust
multi_literal236 ms12.89 ms5.32 ms18x2.4x slowerRust
char_class507 ms41.91 ms58.38 ms12x1.4x fastercoregex
alpha_digit255 ms29.02 ms13.48 ms9x2.2x slowerRust
word_digit269 ms29.22 ms13.59 ms9x2.2x slowerRust
word_repeat647 ms179 ms56 ms3.6x3.2x slowerRust
anchored0.04 ms0.05 ms0.04 ms~1x~same
anchored_php0.05 ms0.06 ms0.38 ms~1x~same

coregex v0.12.23 — Multi-engine architecture with 17 strategies, SIMD prefilters, zero-allocation Aho-Corasick v0.3.0. Run make extreme for 2500x demo.

Key Findings

Go coregex v0.12.23 vs Go stdlib:

  • All patterns: 3.6-893x faster
  • Best: inner_literal 893x, ip 635x, email 467x
  • uri 424x, multiline_php 266x, version 250x
  • suffix 132x, http_methods 68x, literal_alt 49x
  • char_class 12x (CharClassSearcher, faster than Rust!)
  • word_repeat 3.6x (flat DFA with 4x unrolling)

Go coregex faster than Rust (6 patterns):

  • inner_literal: coregex 52x faster (0.26ms vs 13.55ms)
  • ip: coregex 17.6x faster (0.77ms vs 13.53ms)
  • suffix: coregex 7.7x faster (1.79ms vs 13.70ms)
  • multiline_php: coregex 2.0x faster (0.38ms vs 0.76ms)
  • char_class: coregex 1.4x faster (41.9ms vs 58.4ms)
  • version: coregex 1.2x faster (0.65ms vs 0.79ms)

Rust faster than coregex:

  • literal_alt: Rust 7.4x faster (Teddy with more buckets)
  • word_repeat: Rust 3.2x faster (DFA state acceleration)
  • multi_literal: Rust 2.4x faster
  • http_methods: Rust 2.4x faster
  • alpha_digit, word_digit: Rust 2.2x faster
  • email: Rust 2.1x faster
  • uri: Rust 1.8x faster

Note: Rust regex has 10+ years of development. coregex optimizations are targeted, not universal.

Analysis

EngineStrengthsWeaknesses
Go stdlibSimple, no dependenciesNo optimizations, 3.6-893x slower
Go coregexFlat DFA, reverse search, SIMD prefilters, Aho-Corasick, bidirectional DFA, 6 patterns faster than RustTeddy Go/ASM gap, word_repeat
Rust regexDFA state acceleration, Teddy Fat, mature DFAip, inner_literal, suffix, multiline_php, char_class, version slower than coregex

v0.12.23 (Current):

  • 17 strategies: NFA, DFA, OnePass, BoundedBacktracker, Teddy, Aho-Corasick, reverse search, and more
  • Flat DFA transition table (Rust approach) — single flat array, no pointer chase
  • SIMD prefilters: AVX2 memchr, SSSE3/AVX2 Teddy, Aho-Corasick DFA
  • Zero-allocation API: Find/FindAt/IsMatch with no heap allocations
  • 6 patterns faster than Rust: inner_literal (52x), ip (17.6x), suffix (7.7x), multiline_php (2.0x), char_class (1.4x), version (1.2x)

Historical Improvements:

  • v0.12.23: Aho-Corasick v0.3.0 (zero-alloc Find/FindAt API)
  • v0.12.22: Lazy memory architecture — 5-7x memory reduction per pattern
  • v0.12.18: Flat DFA transition table, integrated prefilter, 4x unrolling — 3x from Rust
  • v0.12.17: Fix LogParser ARM64 regression, restore DFA/Teddy for (?m)^
  • v0.12.16: WrapLineAnchor for (?m)^ patterns
  • v0.12.15: Per-goroutine DFA cache, 7 correctness fixes, stdlib compat test (38/38)
  • v0.12.14: Concurrent isMatchDFA safety fix (#137)
  • v0.12.13: FatTeddy AVX2 fix, prefilter acceleration, AC v0.2.1
  • v0.12.1: Bidirectional DFA fallback, bounded repetitions fix (#115), AVX2 Teddy fix (#74)
  • v0.12.0: Anti-quadratic guard, DFA loop unrolling, DFA cache clear & continue
  • v0.11.4: FindAll multiline fix, 78x faster (Issue #102)
  • v0.11.3: UseMultilineReverseSuffix prefix fast path 319-552x (Issue #99)
  • v0.11.1: UseMultilineReverseSuffix for multiline patterns (Issue #97)
  • v0.11.0: UseAnchoredLiteral 32-133x speedup (Issue #79)
  • v0.10.10: ReverseSuffix CharClass Plus fix
  • v0.10.9: UTF-8 optimization + fuzz-found bug fixes
  • v0.10.8: FindAll allocation fix for anchored patterns
  • v0.10.7: UTF-8 fixes + 100% stdlib API compatibility
  • v0.10.5: CompositeSearcher backtracking fix
  • v0.10.0: Fat Teddy AVX2 (33-64 patterns, 9+ GB/s)
  • v0.9.5: Aho-Corasick integration, Teddy 32 patterns

Extreme Speedups (1000-3000x)

The "3-3000x faster" claim refers to specific edge cases where coregex prefilters can skip entire input:

make extreme       # Run on no-match data (~300-560x)
make extreme-3000x # Run on no-digits data (1000-3000x)

GitHub Actions Ubuntu results (6 MB no-digits data, v0.12.1):

PatternGo stdlibGo coregexSpeedup
ip_nomatch422 ms166 µs2542x
suffix_find245 ms126 µs1945x
phone_nomatch143 ms166 µs863x
inner_nomatch229 ms382 µs598x

Extreme Benchmark

Note: Results vary between runs (±30%) due to CI VM load and OS scheduling. The key insight: coregex operates in microseconds, stdlib in hundreds of milliseconds.

When do we see 3000x?

The 3000x speedup occurs in coregex's own benchmark suite (go test -bench) under specific conditions:

  • Pattern: IP regex on data with NO IP addresses
  • Size: 1 MB of pure text
  • Measurement: go test -bench with multiple iterations
// In coregex repo:
BenchmarkIPRegex_Find/stdlib_1MB_no_ips    74.5ms
BenchmarkIPRegex_Find/coregex_1MB_no_ips   22.4µs  // 3324x

The extreme speedup happens because:

  1. DigitPrefilter scans for first digit character
  2. No digits in input → entire 1 MB skipped in ~20µs
  3. stdlib must scan byte-by-byte → 74ms

Verified speedups (from coregex repo, docs/dev/SPEEDUP_VERIFICATION.md):

PatternStrategyMax Speedup
IP no-match (1MB)DigitPrefilter3324x
.*\.txt$ (1MB)ReverseSuffix1124x
.*error.* (32KB)ReverseInner909x

The speedup depends on input characteristics. Real-world mixed data shows 15-560x.

Patterns Tested

NamePatternTypeOptimization
literal_alterror|warning|fatal|critical4-literal alternationTeddy SIMD
multi_literalapple|banana|...|orange12-literal alternationAho-Corasick
anchored^HTTP/[12]\.[01]Start anchor
inner_literal.*@example\.comInner literalReverse search
suffix.*\.(txt|log|md)Suffix matchReverse search
char_class[\w]+Character classCharClassSearcher
email[\w.+-]+@[\w.-]+\.[\w.-]+Complex real-worldMemmem SIMD
uri[\w]+://[^/\s?#]+[^\s?#]+...URL with query/fragmentMemmem SIMD
version\d+\.\d+\.\d+Version numbersDigitPrefilter
ip(?:(?:25[0-5]|2[0-4][0-9]|...)\.){3}...IPv4 validationDigitPrefilter + LazyDFA
http_methods(?m)^(GET|POST|PUT|DELETE|PATCH)Multiline log parsingBranchDispatch
anchored_php^/.*[\w-]+\.phpURL path matchingUseAnchoredLiteral
multiline_php(?m)^/.*\.phpMultiline PHP pathsUseMultilineReverseSuffix
word_repeat(\w{2,8})+Word quantifiersBoundedBacktracker + DFA fallback

Running Benchmarks

# Generate input data (6 MB)
go run scripts/generate-input.go

# Build for Linux
cd go-stdlib && GOOS=linux GOARCH=amd64 go build -o ../bin/go-stdlib-linux . && cd ..
cd go-coregex && GOOS=linux GOARCH=amd64 go build -o ../bin/go-coregex-linux . && cd ..

# Run all in WSL/Linux for fair comparison
wsl ./bin/go-stdlib-linux input/data.txt
wsl ./bin/go-coregex-linux input/data.txt
wsl ./bin/rust-benchmark input/data.txt

CI Benchmarks

Benchmarks run automatically on GitHub Actions (Ubuntu) for reproducible results.

Benchmark

Auto-generated comparison table in Job Summary:

  • Side-by-side results for all 3 engines
  • Speedup calculations (vs stdlib, vs Rust)
  • Winner column with bold formatting
  • Raw output in collapsible section

License

MIT