High-performance regex matching for R using Rust via extendr. Compares multiple implementations including base R, parallel R (mirai/furrr), and Rust (regex and fancy-regex engines).
string_detect() function with smart defaultsfixed = TRUE
stringr::str_detect()
# Install Rust first: https://rustup.rs/
# Then install the package
devtools::install()
library(stringrs)
# Simple detection with smart defaults
strings <- c("apple pie", "banana bread", "cherry tart")
pattern <- "a[aeiou]"
string_detect(strings, pattern)
# Multiple patterns - returns wide tibble
patterns <- c("a[aeiou]", "[bt]read", "^ch")
result <- string_detect(strings, patterns)
# Returns: tibble with columns: string, a.aeiou., X.bt.read., X.ch
# Fixed (literal) matching - bypasses regex for speed
strings <- c("Hello world", "hello there", "HELLO")
string_detect(strings, "hello", fixed = TRUE) # case-sensitive literal match
string_detect(
strings, # Character vector of strings to search
pattern, # Character vector of patterns (single or multiple)
fixed = FALSE # Use literal matching (bypasses regex)
)
Parameters:
strings: Character vector of strings to searchpattern: Character vector of patterns (single pattern or multiple patterns)fixed: Logical. If TRUE, use literal string matching (bypasses regex engine for speed). Default is FALSE (regex matching).Returns:
strings)string columnAuto-optimization (all transparent):
# Quick test (reduced test cases, single iteration)
Rscript benchmark/run.R --quick
# Full benchmark suite (19 scenarios)
Rscript benchmark/run.R
# Custom workers and iterations
Rscript benchmark/run.R --workers 8 --iterations 5
# Include comparison to previous runs
Rscript benchmark/run.R --compare
The benchmark suite tests various scales:
| Test | Strings | Patterns | Description |
|---|---|---|---|
| 1Kx1 | 1,000 | 1 | Small single pattern |
| 10Kx1 | 10,000 | 1 | Medium single pattern |
| 100Kx1 | 100,000 | 1 | Large single pattern |
| 1Kx10 | 1,000 | 10 | Small multi-pattern |
| 10Kx10 | 10,000 | 10 | Medium multi-pattern |
| 100Kx10 | 100,000 | 10 | Large multi-pattern |
| 10Kx50 | 10,000 | 50 | Many patterns |
| 10Kx100 | 10,000 | 100 | Very many patterns |
grepl(), stringr::str_detect(), stringi::stri_detect_regex()
future_map() over strings or patternsSet fixed = TRUE when:
Example: string_detect(text, "ERROR", fixed = TRUE)
The package automatically optimizes based on your data:
(.)\1 or lookaheads (?=...) auto-detect fancy-regex needAdvanced users can tune via R options:
# Adjust chunking threshold (in bytes)
options(stringrs.chunk_threshold = 50 * 1024 * 1024) # 50MB
# Reset to default
options(stringrs.chunk_threshold = NULL)
All performance decisions happen transparently:
Engine Selection
Parallel Strategy
Memory Chunking
stringrs/
├── R/
│ ├── extendr-wrappers.R # Auto-generated Rust bindings
│ └── string_detect.R # Main R API (single function)
├── src/
│ └── rust/
│ ├── src/lib.rs # Rust implementation
│ └── Cargo.toml # Rust dependencies
├── benchmark/
│ ├── run.R # Benchmark runner
│ ├── engines.R # Engine implementations
│ ├── scenarios.R # Test scenarios
│ ├── metrics.R # Performance metrics
│ ├── visualize.R # Result visualization
│ └── compare.R # Baseline comparison
└── tests/
└── testthat/
└── test-detect.R # Unit tests
To add a new regex implementation:
src/rust/src/lib.rs
extendr_module!
R/extendr-wrappers.R
inst/benchmark_functions.R
MIT + file LICENSE