152 lines
9.1 KiB
Markdown
152 lines
9.1 KiB
Markdown
# Performance
|
|
|
|
Live parsing is debounced by 120 ms and live execution by 220 ms. Live runs use
|
|
a 250 ms wall-clock limit; manual runs default to 2 seconds and can be raised to
|
|
the configured 10-second maximum.
|
|
|
|
Tests exercise bounded parsing, execution, zero-length iteration, result
|
|
truncation and worker recovery. Browser performance depends on hardware,
|
|
browser, engine version, pattern and subject. The UI therefore reports observed
|
|
elapsed time and exact runtime identity but makes no universal throughput or
|
|
safety claim.
|
|
|
|
PCRE2 cold worker startup includes loading and instantiating the self-hosted
|
|
WebAssembly module; warm requests reuse that instance.
|
|
Every request still compiles and frees its pattern so no unbounded compiled-code
|
|
cache can accumulate. Native match-step, depth and heap limits complement the
|
|
supervisor wall clock, and cancellation discards the complete worker heap.
|
|
|
|
Python has a materially larger cold start because its worker loads the
|
|
self-hosted Pyodide JavaScript/WebAssembly runtime and Python standard library
|
|
before verifying CPython and `re`. Java imports and self-tests its bundled
|
|
TeaVM ES module. Scala compatibility shares that Java module and does not load
|
|
a second runtime.
|
|
|
|
PHP, legacy Perl, Ruby, Go, Rust, C++ and .NET likewise load only when first
|
|
selected. Their cold cost differs substantially: PHP, Perl, Ruby and .NET
|
|
instantiate larger language/runtime packs; Go includes its standard
|
|
WebAssembly runtime; Rust and C++ are comparatively compact native modules.
|
|
The UI reports loading separately rather than charging it to the 250 ms live or
|
|
selected manual execution timeout.
|
|
|
|
Warm requests reuse a verified worker. To prevent profile exploration from
|
|
leaving every large runtime resident, the supervisor uses a two-worker
|
|
retention target and evicts the least recently used idle generation before it
|
|
creates another profile worker. An active request is never evicted, so
|
|
concurrent active work can temporarily exceed the target. Killing or evicting
|
|
a worker discards its complete runtime, so the next request pays the cold-load
|
|
cost and verifies identity again.
|
|
|
|
Automatic-callout tracing is deliberately excluded from every benchmark. It
|
|
compiles an independently instrumented PCRE2 pattern in a separate worker and
|
|
can materially change runtime work. The trace path retains at most 50,000
|
|
complete 32-byte event records and 10 MiB total serialized event/mark bytes;
|
|
the viewer renders at most 2,000 retained events.
|
|
|
|
The production bundle separates syntax and execution workers. Interactive
|
|
syntax/extraction trees and editor decoration sets render at most 2,000 items
|
|
each and report both the rendered and actual totals. These are presentation
|
|
limits only: normalized syntax, exact ranges and bounded engine results remain
|
|
available to the capture table and eligible exports.
|
|
|
|
Replacement templates have a 64 Ki UTF-16 input limit. Every token below that
|
|
limit remains in the syntax model; the editor decorates at most 2,000 tokens,
|
|
the token list renders 500 rows, and at most 200 replacement diagnostics
|
|
(including an omission summary) cross into the UI. List templates have a 16 Ki
|
|
UTF-16 input limit and render 250 token chips.
|
|
|
|
The per-match replacement view renders at most 200 matches and 2,000
|
|
contributions, with a combined 50,000 token-evaluation budget. Original,
|
|
replacement and individual contribution text are previewed separately from the
|
|
bounded output.
|
|
|
|
Capture rows are collected under the central 100,000-row limit and rendered in
|
|
pages of 200. Individual result-value previews are capped at 64 Ki UTF-16 units
|
|
and share an 8 Mi-unit aggregate engine-result budget. The extraction tree
|
|
shows 100 UTF-16 units per value and capture-table cells show 512, with explicit
|
|
range lengths and separate engine-prefix labels; copy and eligible JSON export
|
|
retain the bounded engine value. List export is disabled when a source value is
|
|
incomplete, so a bounded preview cannot be mistaken for the full value. List
|
|
generation additionally stops at 250,000 template-token evaluations, a 64 Ki
|
|
UTF-16 row preview, or an 8 Mi-unit aggregate materialization bound. The UI
|
|
shows 500 list rows while an eligible export still contains every generated
|
|
row; any incomplete result disables export.
|
|
Replacement output has a separate 64 MiB bound. Match/capture-limit
|
|
incompleteness and output-byte truncation are tracked separately; either makes
|
|
the aggregate replacement result incomplete.
|
|
|
|
Unit-test cases run through supervisors separate from the interactive workers.
|
|
Each case uses its configured timeout, cancellation kills the active worker,
|
|
and the suite has a 60-second aggregate wall limit. Suite state is capped at
|
|
1,000 cases; add, clone, current-result capture and JSON append-import all
|
|
enforce that cap and preflight a 32 MiB aggregate in-memory suite bound. Test
|
|
names, patterns, subjects, replacement templates and expected values have
|
|
explicit per-field limits; subjects must also fit the execution engine's UTF-8
|
|
byte cap. Failure diagnostics preview only bounded portions of expected and
|
|
actual values and retain at most 2 KiB UTF-8 per result, keeping 1,000 result
|
|
messages below the 2 MiB log budget. A complete replacement output above the
|
|
expected-value or aggregate-suite limit is not copied into draft state; a
|
|
lightweight `should-match` draft is offered when applicable.
|
|
|
|
Project import, export and local save have a 32 MiB aggregate UTF-8 JSON limit
|
|
in addition to field-specific limits. Standalone test-suite import has the same
|
|
32 MiB pre-parse file/document limit. Export and save count the indented JSON
|
|
representation against a byte budget before materializing or writing it.
|
|
IndexedDB schema version 2 indexes `updatedAt`; latest-project loading opens one
|
|
descending cursor and validates only that record instead of calling `getAll()`.
|
|
|
|
Corpus runs accept at most 256 documents, 16 MiB per document and 256 MiB of
|
|
aggregate UTF-8 input. Jobs run sequentially so only one engine request is
|
|
active at a time. A batch retains at most 100,000 matches and 64 MiB of applied
|
|
output, and stops after five minutes of aggregate wall time. Each document also
|
|
uses the selected manual timeout. Progress is reported after every document;
|
|
cancellation kills the current worker and labels all remaining documents.
|
|
Result tables contain summaries, not match/capture objects. ZIP export is
|
|
available only for an all-exact apply batch and is created asynchronously.
|
|
|
|
Independent-line mode preflights at most 100,000 logical lines and processes
|
|
each as an isolated engine subject while preserving line separators for exact
|
|
apply output. Per document, corpus extraction retains at most 32 group summaries
|
|
(including the full match), three 160-UTF-16-unit samples per group and 100
|
|
unique diagnostics. Output previews show 2,000 units. Content-free summary
|
|
exports are capped at 4 MiB; the applied archive is capped at 68 MiB in addition
|
|
to the 64 MiB uncompressed-output budget.
|
|
|
|
ECMAScript analysis reports cold compilation separately from warm native
|
|
execution. The default benchmark uses three warm-up and 15 measured samples;
|
|
user caps are 100 warm-ups and 1,000 samples. It reports median and
|
|
nearest-rank p95 values plus separate timing and outcome/growth plots with the
|
|
exact runtime identity. Each sample defaults to a 2-second killable-worker
|
|
limit (10-second cap), and the aggregate analysis wall time is 30 seconds.
|
|
|
|
Growth probes retain at most 24 steps, generate at most 1 MiB by default under
|
|
the central 16 MiB subject cap, and reject more than 10,000,000 repetitions
|
|
before string allocation. Replacement timing is skipped when match collection
|
|
is truncated or the estimated output exceeds 8 Mi UTF-16 units. Results are
|
|
observations for the chosen runtime and generated inputs, never a general
|
|
complexity proof. See [`ANALYSIS.md`](ANALYSIS.md).
|
|
|
|
Generated-case synthesis defaults to 48 retained cases from at most 192
|
|
candidates, 16 seeded-random variants, 64 KiB per candidate, 1 MiB aggregate
|
|
candidate bytes and 15 seconds of aggregate wall time. Every candidate then
|
|
uses a separate selected-engine request with a 500 ms default timeout.
|
|
Generation preflights UTF-8 size and repetition bounds, caps normalized-AST
|
|
traversal at 20,000 nodes / 512 levels and retains only bounded diagnostics.
|
|
Hard caps are documented in [`GENERATED_CASES.md`](GENERATED_CASES.md).
|
|
|
|
Subject minimization accepts at most 1 MiB UTF-8, performs at most 2,000 real
|
|
engine candidate evaluations and stops after at most 60 seconds including
|
|
syntax setup. One fixed worker timeout of at most 10 seconds applies to every
|
|
candidate. A candidate starts only when that complete deadline fits in the
|
|
remaining aggregate budget. Accepted-transform history retains 200 entries;
|
|
evaluation and accepted totals remain exact. See
|
|
[`MINIMIZATION.md`](MINIMIZATION.md).
|
|
|
|
Formatter validation uses two syntax supervisors and two actual-engine
|
|
supervisors so source/candidate outcomes cannot share compiled state. The
|
|
current subject/replacement snapshot always runs; at most 1,000 enabled tests
|
|
with the exact active identity are replayed. Test validation has a 60-second
|
|
aggregate wall budget, and a test starts only when its complete configured
|
|
worker timeout still fits. Preview details retain at most 10,000 transforms and
|
|
the UI renders the first 200. See [`FORMATTING.md`](FORMATTING.md).
|