# Performance and risk analysis Regex Tools provides one deliberately scoped analysis implementation: ECMAScript 2025 patterns parsed into the application-owned normalized AST and executed by the browser's native `RegExp` runtime. The analyser does not apply ECMAScript findings to PCRE2, Python, Java or any other flavour. Analysis is advisory. The UI uses “potential risk”, “possibly” and “observed under selected limits”. It never turns an empty finding list into “safe”, “guaranteed linear” or a vulnerability proof. ## Static analysis The application-owned `regex-tools-ecmascript-heuristics` analyser walks at most 20,000 normalized nodes and returns at most 100 findings. Each finding contains: - flavour and UTF-16 source range; - stable rule identifier; - static or dynamically observed provenance; - explanation and example risk; - low, medium or high confidence; - limitations; - a suggested investigation. The current rules review nested and nullable repetition, ambiguous repeated alternatives, overlapping alternative prefixes, wildcards and backreferences inside repetition, repeated lookaround bodies, unanchored amplification, capture count, nesting depth and replacement-output expansion. These are structural heuristics. They do not model the native engine's complete compiled program, optimizations or calling context. ## Dynamic growth probes The user defines a bounded subject family: ```text prefix + repeatedFragment.repeat(repetitions) + suffix ``` The byte and UTF-16 size are calculated before the generated string is allocated. The repeated fragment is limited to 4,096 UTF-16 units, each affix to 16,384 units, the run to 24 samples, and repetitions to 10,000,000. The UI defaults to a 1 MiB generated-subject cap even though the central interactive hard cap remains 16 MiB. Every probe executes in a dedicated worker. The supervisor terminates and discards that worker on per-sample timeout, cancellation or crash. Runs also stop at: - the selected repetition bound; - the selected generated-byte bound; - the selected step bound; - the 30-second aggregate wall bound; - a selected normalized-growth threshold. The growth threshold compares the time ratio with the input-size ratio for two adjacent samples. Sub-millisecond measurements below a noise floor do not trigger it. A threshold observation characterizes only those generated inputs and that browser. Timeout, crash, compile rejection and non-match remain distinct states. The UI renders time and outcome in separate plots and keeps the exact sample table alongside them. ## Benchmark method A benchmark begins with a fresh analysis worker. Worker creation and its identity response form the separate cold-start measurement. The first native engine use is retained as a cold sample. Configured warm-up samples are discarded; configured measured samples produce the warm statistics. Each sample measures these phases separately: - `RegExp` construction; - first `exec`; - bounded all-match iteration; - native string replacement when its conservative output bound is acceptable; - all-match throughput and match count. All-match iteration retains only counts, not values or captures. It follows the same explicit scan-all, global, sticky and Unicode zero-length advancement semantics as the workbench. The application-added indices flag remains in the effective flags so the measured operation reflects interactive execution. Replacement timing is skipped when match collection reaches its bound or a conservative estimate can exceed 8 Mi UTF-16 units. This prevents a benchmark from using an unbounded native replacement merely to obtain a timing. It is also skipped for explicit scan-all with sticky `y`: native `String.replace` processes only one sticky match, while the workbench's explicit scan-all operation can process a contiguous sequence. Reporting that different operation as the same benchmark would be misleading. Warm metrics include sample count, minimum, conventional median, nearest-rank p95 and maximum. Milliseconds are shown to two decimal places, with values below 0.01 ms labelled accordingly; this does not imply nanosecond accuracy. The result retains subject size, match count, effective flags, browser runtime identity and engine identity. Defaults: | Setting | Default | Hard bound | | ----------------------- | ------: | ---------: | | Warm-up samples | 3 | 100 | | Measured samples | 15 | 1,000 | | Per-sample timeout | 2 s | 10 s | | Aggregate wall time | 30 s | 30 s | | Matches per sample | 10,000 | 10,000 | | Replacement output gate | 8 MiU | 8 MiU | One subject is not a complete performance characterization. Results from different algorithms, pattern ports, browser engines, WebAssembly runtimes or machines are not directly comparable. Trace-enabled execution is never used for benchmark results. ## Privacy and persistence Patterns, subjects, generated inputs, findings and benchmark samples remain in the browser. No analysis request is uploaded. Analysis settings and results are currently ephemeral and are not added to project JSON or IndexedDB; this also keeps large benchmark subjects out of persisted projects by default.