diff --git a/CONTEXT.md b/CONTEXT.md index 3d57211..4d4d423 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -56,26 +56,26 @@ substring engine — and it is absent from every caseless benchmark: no dedicated caseless substring engine exists in that suite at all; the caseless columns are contested only by general regex engines. -**Direct rebar audit (2026-08-17):** `casei` was wired into every caseless -literal or finite-alternation definition at rebar commit `463d00f`: 18 +**Direct Rebar audit (2026-08-24):** `casei` was wired into every caseless +literal or finite-alternation definition at Rebar commit `463d00f`: 18 performance workloads and three semantic checks. Rebar's pinned [performance models](https://github.com/BurntSushi/rebar/blob/463d00f31887e84c38467805b9e3122c314b9521/MODELS.md) -enumerate every non-overlapping match, rather than return the first. Five rows -enable Unicode folding and therefore share this repository's folding contract; -against the selected current leaders, the loop-over-`Find` adapter wins two and -loses three on both Ice Lake and Sapphire Rapids, with the five-pattern Russian -row losing by roughly 9× to Hyperscan. Thirteen additional performance rows -request ASCII-only case matching; they were run and output-verified, but -`casei` retains stronger Unicode semantics. [`REBAR.md`](REBAR.md) records -every row, both-host ratios, -the incompatible `s`/`ſ` behavior check, and the causal diagnosis. Instrumented -reproduction showed that a stateful one-pass enumerator did not improve the 9× -row: the five-pattern plan filters on common Cyrillic roots, admits 21.7% of the -corpus into rune decoding and token-map verification, and never gains the rare -interior pair-pair anchors selected for a single pattern. The missing iterator -is therefore an API gap, not the primary performance gap. These measurements -bound the result here to the 33-row arena contract; Rebar's non-overlapping -enumeration numbers cannot be borrowed in support of it. +enumerate every non-overlapping match. Five rows enable Unicode folding and +share this repository's contract. The first audit won two and lost three on +both Ice Lake and Sapphire Rapids; its five-pattern Russian row was roughly 9× +behind Hyperscan. Instrumentation put the loss in a shared filter over common +Cyrillic starts and decoded confirmation, rather than in repeated API setup. + +That result opened the missing cells. The retained follow-up combines tagged +interior anchors, exact pair replay, one/two/three-byte raw confirmation with +source-width return, and an exact common-byte origin gate. The current adapter +uses `Matcher.Each` and wins all five same-contract rows on both hosts. Its +worst ratios are 0.8794 on Ice Lake and 0.8999 on Sapphire Rapids. Thirteen +additional rows request ASCII-only matching; they remain visible as +different-contract stress data, with `casei` winning 9 of all 18 rows on each +host. [`REBAR.md`](REBAR.md) records the before/after mechanisms, complete +table, incompatible `s`/`ſ` behavior check, and raw receipts. The arena now +contains three focused rows derived from the gap and has 36 rows in total. **Correction (v2, after a three-way prior-art sweep):** dedicated engines DO exist, with different contracts: diff --git a/HOW_IT_WORKS.md b/HOW_IT_WORKS.md index 63f6f61..a1c951a 100644 --- a/HOW_IT_WORKS.md +++ b/HOW_IT_WORKS.md @@ -1,213 +1,287 @@ # How casei works -`casei` gets most of its speed by using a few raw-byte tests before it decodes -Unicode. - ## Ten seconds -It compiles each pattern set into two parts that agree: +`casei` does cheap byte tests before it pays for Unicode. + +It compiles a pattern set into one exact search plan and a set of conservative +byte filters. The filters reject impossible starts in blocks. The exact plan +checks every survivor. ```text exact fold-token plan / \ -patterns -> compile once -> first correct match +patterns -> compile once -> leftmost correct match \ / - cheap raw-byte sieve - (64 starts per block) + conservative byte sieve +``` + +The sieve may say "maybe" too often. It may never skip a real match. That one +rule lets the fast path use compact byte tables while the plan keeps complete +Unicode semantics. + +## One minute + +Suppose the text is one megabyte long and the pattern is `fatal panic`. +Checking every byte as a possible start repeats almost the same failure over +and over. + +At compile time, `casei` chooses byte positions that are useful for this exact +literal. On AVX-512, one comparison covers 64 possible starts. A few comparison +masks are intersected: + +```text +candidate start 0 1 2 3 4 5 ... 63 +probe at offset A 0 0 1 0 0 0 ... 0 +probe at offset B 0 0 1 0 1 0 ... 0 +probe at offset C 0 0 0 0 1 0 ... 0 + -------------------- AND +survivors 0 0 0 0 0 0 ... 0 ``` -The sieve rejects impossible starting positions without declaring a match. It -usually rejects all 64 positions in a block. The complete Unicode plan checks -any survivors. Every real start reaches that plan, along with false positives -that cost an extra check. +No survivor means the whole block is done. A survivor is replayed through the +exact plan. That plan decides the match, source byte offset, leftmost order, +and pattern-ID tie. + +The compiler can choose adjacent pairs, dispersed bytes, triples, Shufti-style +tables, pair-pair filters, or tagged multi-pattern anchors. The choice comes +from the compiled pattern shape. It never comes from the benchmark name. + +## Why the advantage exists + +The advantage has three layers. + +### 1. A smaller question + +The input is a literal or finite set of literals under Unicode simple folding. +The answer is the first leftmost match, or a stream of non-overlapping matches. -## One minute: searching one block +A regex engine must preserve classes, captures, repetition, lookarounds, and +the rest of its language. `casei` can spend compilation on literal-specific +byte positions and a literal-specific confirmation plan. Arena adapters make +every entrant answer the same result contract and charge any adaptation to the +entrant being adapted. -Imagine looking for `fatal panic` without case sensitivity. +### 2. Less work -Checking every possible start spends time on positions that cannot match. Fast -search engines use filters to skip that work. `casei` specializes its filters -for literal strings under Unicode simple folding. The caller asks for one -leftmost answer. +Most bytes never reach the Unicode executor. A block filter proves that no +match can start at any of 64 positions. Multi-pattern filters also return an +eight-bit pattern tag, so the exact replay checks only the literals named by +the surviving lane. -`casei` knows at compile time that this is a literal. It chooses useful byte -positions far enough apart to make accidental alignment rare when the pattern -permits it. On AVX-512 it loads those positions for 64 possible starts at once, -compares their case-normalized bytes, and intersects the resulting 64-bit masks. +The current focused paths add two more pieces: + +- A single Unicode literal can compile its one-, two-, and three-byte fold + spellings into a bounded raw confirmation. The confirmer advances by the + spelling that matched and returns the source width it proved. +- An eligible multi-pattern plan can choose an exact ASCII byte present in + every spelling of every literal. The first occurrence bounds where a match + could begin. A dedicated kernel scans eight 64-byte blocks before it tests + the ordered masks. + +Both are gates into the same plan. Neither is a second matcher. + +The [two-host ablations](audit/acceptance/ablations/README.md) remove the origin +gate, variable confirmation, and returned pattern tags one at a time. Each +removal loses a required focused field or Rebar row on at least one host. + +### 3. Hardware-shaped kernels + +AVX-512 BW compares 64 bytes at a time. VBMI performs byte-table lookup in a +register. Mask registers hold candidate sets without converting them back to +ordinary vectors. + +Instruction latency still matters. On Ice Lake, OpcodeX reports three-cycle +latency and one-per-cycle reciprocal throughput for the unmasked ZMM `VPERMB` +used by the hot table loops. A loop that starts one block and waits leaves issue +slots unused. The hand-written kernels carry independent blocks through those +three cycles. + +The exact common-byte gate is a simple example: ```text -candidate starts 0 1 2 3 4 5 ... 63 -probe at offset A 0 0 1 0 0 0 ... 0 -probe at offset B 0 0 1 0 1 0 ... 0 -probe at offset C 0 0 0 0 1 0 ... 0 - -------------------- AND -survivors 0 0 0 0 0 0 ... 0 +load+compare block 0 -> k0 +load+compare block 1 -> k1 +... +load+compare block 7 -> k7 +ordered pair tests find the first non-empty mask ``` -When no bit survives, the search advances by a block. Otherwise `casei` replays -the complete pattern at each surviving byte position. +OpcodeX reports the memory-source `VPCMPEQB` form at three-cycle latency and +one-per-cycle throughput on Ice Lake. Its current uops.info catalog has no +Sapphire Rapids column, so the instruction table is used only to explain the +Ice Lake schedule. Eight independent compares give the core work while earlier +masks are in flight. The Sapphire Rapids result comes from direct execution and +the complete field measurements. -The compiler chooses among dispersed single-byte probes, adjacent pairs, -pair-pair anchors, triples, and bounded Shufti/Teddy-style tables. The choice is -made from facts proved about the compiled patterns. +The tagged multi-anchor kernel uses the same idea with `VPERMB` tables. Its +common sparse path proves eight blocks empty. A hit returns to a four-block +dispatcher, preserves byte order, extracts the first lane's tag byte, and lets +Go perform exact pair and plan checks only for those tags. -## Why Unicode does not break the sieve +
+Unicode coverage and the shared multi-pattern plan -Lowercasing both strings cannot implement Unicode simple folding. Each pattern -position represents an orbit of equivalent runes, whose UTF-8 encodings may -have different lengths: +## Unicode without hand-waving + +Lowercasing both strings is a different operation. Simple folding groups runes +into orbits: ```text k K K one byte, one byte, three bytes s S ſ one byte, one byte, two bytes -σ ς Σ three different runes in one orbit +σ ς Σ three runes in one orbit ``` -`casei` first compiles the complete relation into tokens. Valid runes map to -their fold-orbit token. Invalid UTF-8 bytes map to separate opaque tokens. The -shared state machine advances over those tokens and owns all semantic decisions. - -Raw-byte filters are then derived only where they are safe: +`casei` compiles each orbit to one token. Valid haystack runes map to those +tokens. Invalid UTF-8 bytes map to opaque one-byte tokens. The shared state +machine advances over tokens and owns the answer. -- A fixed ASCII probe is used only when its offsets remain valid for every - relevant rendering. -- Pair and triple tables contain every raw UTF-8 form that could begin the - corresponding token sequence. -- Low-bit table aliases and normalized Shufti buckets are allowed to add - survivors, because the exact plan follows them. -- A route is disabled when the compiler cannot prove that its filter covers - every possible start. +Raw filters are derived from that plan under coverage proofs: -Every filter must cover each encoding of every real start. Extra survivors are -checked by the exact plan. +- Fixed offsets are used only while every earlier fold spelling has the same + width. +- Pair and triple tables contain every possible raw spelling for the token + window they represent. +- A low-six-bit `VPERMB` alias may create a false survivor. Exact replay removes + it. +- Variable confirmation stores complete raw forms and advances by the form + that matched. +- A filter route is disabled when the compiler cannot prove coverage. -## Many patterns in one scan +This makes false positives a performance cost. False negatives are a +correctness bug. -`NewMatcher` compiles every pattern into one trie with failure transitions over -fold tokens. Depending on its size, the same state machine uses a dense -transition table or sparse edges. +## One pattern and many patterns -The filters summarize possible starts across the whole pattern set. One pass -over the haystack therefore serves one pattern or hundreds: +`NewMatcher` compiles the whole set into a trie with failure transitions over +fold tokens. Small plans use sparse edges. Larger plans can materialize dense +transitions. ```text -N=1 one compiled plan, one filter, one scan -N=512 one shared plan, shared filters, one scan +N=1 one plan, one traversal +N=8 one shared plan, tagged filters, one traversal +N=512 one shared plan, shared filters, one traversal ``` -Terminals record pattern IDs. The plan delays its answer only as far as needed -to prove the leftmost byte position; ties go to the lowest original pattern -index. +Terminals carry the original pattern ID. The plan waits only long enough to +prove the leftmost source byte. Equal starts choose the lowest ID. -## Where the advantage comes from +The tagged Unicode route is important for enumeration. Each literal contributes +selective interior pairs and their possible source-start offsets. The vector +screen intersects primary and confirmation pairs while carrying the owning +pattern bits. Exact pair checks remove table aliases. The existing raw token +plan then proves the match and its width. -`casei` works under a narrower contract than the general regex engines in the -field. The compiler receives literals under Unicode simple folding. It also -knows that the caller wants the first leftmost answer, which lets it design the -raw-byte sieve and exact verifier together for the whole pattern set. +
-Four measured layers contribute to the result: +
+Competitor implementations and the assembly A/B -| layer | what it buys | evidence that it matters | -|---|---|---| -| Work avoidance | Whole blocks are rejected without decoding or advancing the exact plan at every byte. | Bypassing the shape-selected routes made the median row 3.88× slower on Ice Lake and 4.28× slower on Sapphire Rapids. Three rows were unchanged within 1%; the worst Unicode multi-pattern rows were 401× and 424× slower. | -| Shared construction | One pattern set becomes one transition plan and one traversal. | Ten paired measurements compared the shared-plan candidate with the earlier per-pattern `IndexFold` loop. The median maximum `x_vs_best` across the 33 rows fell from 6.718 to 0.9123 while the semantic suite stayed green. | -| Wider native transition | AVX-512 BW handles 64 candidate starts and keeps set arithmetic in mask registers; VBMI performs byte-table lookup in registers. | Masking AVX-512 off while retaining the same plans reduced median throughput by 1.72× on Ice Lake and 1.89× on Sapphire Rapids. One Ice Lake row and three Sapphire Rapids rows favored AVX2, mostly short or Unicode verification-heavy cases. | -| Kernel scheduling | Fewer dependent operations keep the wide sieve fed. | Fusing one four-way Shufti reduction improved its 64 KiB kernel by 21.6% and the field row using it by 21.8%. Replacing the complete assembly backend with Go's experimental SIMD package then regressed a required 1 MiB row. | - -The AVX2 backend keeps the same plan and semantics. The published field lead is -specifically the AVX-512 implementation. - -### Why the hand-written kernels matter - -A 512-bit register gives the kernel 64 lanes, while each instruction still has -latency. On Ice Lake, the `VPERMB` lookup used by the hot long-literal filter -takes three cycles to produce an answer. The core can start one lookup each -cycle. The generated Go SIMD loop starts one 64-byte block and waits for its -answer. The assembly loop keeps four independent blocks in flight, filling the -lookup unit while earlier answers arrive. - -The assembly also sends lookup results straight into AVX-512 mask registers -and asks whether any of four masks survived. The generated loop builds another -vector, converts it to a mask, and moves that mask to a general register on -every 64-byte block. In larger Shufti kernels, the generated code spills lookup -tables to 144- and 512-byte stack frames; the assembly keeps them in vector -registers. - -The complete-backend A/B passed correctness. Six alternating-order Ice Lake -runs put the experimental backend at 20.8–23.3 µs/op on -`single/log_miss_1mb`, versus 18.4–20.8 µs/op for assembly. The public -[archsimd Case](https://app.perfloop.ai/t/oss/case_37sjyc8f94) and the -[negative-result record](NOVELTY.md#complete-experimental-go-simd-backend-negative-result) -contain the acceptance decision and falsifier. - -## Where it differs from the field - -Every scoring implementation was built from source and profiled. I then read -the source, generated code, or hot disassembly where its behavior lived. The -detailed prior-art record is in [`CONTEXT.md`](CONTEXT.md). [`NOVELTY.md`](NOVELTY.md) -records the provenance of each adopted technique. - -| entrant | its strength | the verified distinction | +## What the competitors do + +Every scoring entrant is open source. The audit read the level where its hot +answer lives: source, intrinsics, generated assembly, or built-object +disassembly. + +| entrant | strong path in this field | where casei differs | |---|---|---| -| Vectorscan | A mature multi-regex engine with Teddy/FDR-style literal machinery and a 512-bit VBMI target. | It ran at the same vector width on the same CPUs. The full-scan miss rows therefore compare two 512-bit engines. Its all-match API is covered separately in [`REBAR.md`](REBAR.md). | -| PCRE2-JIT | Strong prefix analysis and native JIT code for a broad regex language. | `casei` spends its compile budget on the narrower literal-set contract and can derive filters that need not preserve general regex behavior. | -| rust/regex | Byte-oriented automata plus strong literal extraction and Teddy prefilters. | It carries a general regex representation; `casei` shares one fold-token literal plan and specializes raw filters around its exact start/tie contract. | -| StringZilla | Dedicated SIMD UTF-8 search, including full-fold expansions. | Full folding is a different relation. The arena times the verification needed to reduce its candidates to simple-fold semantics; `casei` represents that relation directly. | -| veloz | Excellent hand-written AVX2 ASCII single-literal search. | Its contract covers one ASCII literal. The comparison with `casei` includes both specialization and the wider ISA. | -| Rust Aho-Corasick | Strong ASCII multi-pattern DFA with a Teddy prefilter. | `casei` extends the shared-plan shape to Unicode fold orbits, variable UTF-8 widths, opaque invalid bytes, and 512-bit filters. | - -The measured result comes from a complete Unicode plan behind shape-specific -raw-byte rejection, shared across the pattern set and accelerated by AVX-512 -kernels. Shufti, Teddy, rare anchors, tries, failure links, `VPERMB`, and -confirmation after a candidate are known techniques. Their combination under -this contract is what produced the new result. - -## How the claims are checked - -1. Seeded single- and multi-pattern differentials and exhaustive - byte-pair filter checks compare each dispatch mode with Go `regexp (?i)` on - valid UTF-8 and the opaque-byte oracle on invalid input. Separate fuzz - targets exercise the same oracles. -2. The filter-route and ISA ablations measure work avoidance and - vector width separately; the Shufti case isolates one assembly change. The - [raw two-host audit](audit/publication/README.md) includes every sample, the - exact ablation, file hashes, and a recomputation script. -3. Every native entrant is rebuilt from pinned source and - checked for its actual dispatched width before it can enter `x_vs_best`. -4. The 33 arena rows, including five overlap-allowed single-needle counts, run - on both Ice Lake and Sapphire Rapids. -5. The direct Rebar integration exposes the non-overlapping enumeration rows - where the current API loses and keeps those results in the record. - -The verified measurements are the [engine Case](https://app.perfloop.ai/t/oss/case_9r9ntnxjd1) -and the [Shufti refinement](https://app.perfloop.ai/t/oss/case_hqryrfd6j4). -The full local field is reproduced by [`scripts/reproduce.sh`](scripts/reproduce.sh). +| Vectorscan 5.4.12 | Mature Teddy, FDR, and vermicelli machinery with a 512-bit VBMI database. The inspected Sapphire Rapids hot miss path entered `avx512vbmi_vermicelliExec`. | `casei` compiles only the simple-fold literal-set question and joins its filter to the same plan that owns leftmost and pattern ties. The arena compares both at 512 bits. | +| PCRE2 10.47 JIT | Native JIT with strong prefix analysis for a general regex language. It reported a 128-bit path here. | `casei` can select several literal-specific byte positions and raw fold spellings without preserving general regex behavior. | +| rust/regex | Automata plus memchr and Teddy prefilters. Eligible observed paths reported AVX2. | `casei` shares one fold-token plan across the literal set and uses AVX-512 masks and VBMI tables around it. | +| StringZilla 5.1.2 | Dedicated SIMD Unicode search with full-fold expansions. | Full folding is a different relation. The arena charges the verification needed to reduce its candidates to simple-fold results. | +| veloz | Hand-written AVX2 search for one ASCII literal. | `casei` answers Unicode and multi-pattern questions and uses 512-bit kernels on the measured hosts. | +| Rust Aho-Corasick | Strong ASCII multi-pattern DFA with a Teddy prefilter. | `casei` extends the shared-plan shape to simple-fold orbits, variable UTF-8 widths, opaque invalid bytes, and AVX-512 filters. | +| Go regexp | Correct simple folding through the standard scalar regexp engine. | It is the semantic floor. `casei` is a compiled literal engine. | + +Shufti, Teddy, rare anchors, tries, failure links, byte-table lookup, and +confirmation after a candidate are known techniques. The result comes from +combining them under this contract and driving the combination to a field +position no entrant held. [`NOVELTY.md`](NOVELTY.md) makes that claim and its +falsifiers explicit. + +## Does the assembly matter? + +Yes. It was measured. + +The complete amd64 backend was re-expressed with Go's experimental +`simd/archsimd` package. It passed direct tests and differential fuzzing. On +the required Ice Lake `single/log_miss_1mb` row, six alternating-order runs put +the generated backend at 20.8 to 23.3 µs/op and `0.878` to `0.913 x_vs_best`. +The assembly control measured 18.4 to 20.8 µs/op and `0.785` to `0.797`. + +The disassembly explains the gap. The generated hot loop handles one block, +materializes a vector intersection, converts it to a mask, and crosses that +mask to a general register on each iteration. The assembly loop interleaves +four independent blocks and produces k-masks directly with `VPTESTMB`. Larger +generated Shufti functions also spill wide tables to 144-byte and 512-byte +stack frames. Their assembly controls keep the tables in vector registers. + +That experiment is public in the +[Go SIMD backend Case](https://app.perfloop.ai/t/oss/case_37sjyc8f94). + +The assembly audit also killed changes that looked attractive on paper: + +- Combining k-masks with seven extra `KORQ` instructions did not reduce the + tested dependency cost. +- `PREFETCHT0` at 512, 1024, 2048, and 4096 bytes was neutral or slower in the + sparse tagged loop. +- Boolean fusion, target alignment, and a BITALG scout failed their paired + controls. + +Removed experiments and their falsifiers live in [`NOVELTY.md`](NOVELTY.md). + +
+ +
+Verification, limits, and code map + +## How the result is checked + +1. Deterministic differentials compare single and multi results with Go + `regexp (?i)` on valid UTF-8 and an opaque-byte oracle on invalid input. +2. `FuzzIndexFold` and `FuzzMatcher` run those same contracts. The current + publication source was fuzzed on the portable ARM path and both AVX-512 + hosts. +3. Direct assembly models cover randomized lengths, every 64-byte boundary, + tails, dense and sparse epochs, false table aliases, and exact source widths. +4. GDB breakpoints on both CPUs proved that the three new native kernels were + reached by their direct tests. +5. Every field entrant is rebuilt from pinned source and checked for actual + dispatch before timing. +6. Three complete paired passes require all 36 arena rows below 1.0 on Ice Lake + and Sapphire Rapids. +7. Three Rebar passes require all five same-contract external rows below 1.0 on + both CPUs. + +The current evidence is in [`audit/acceptance/`](audit/acceptance/README.md) +and [`audit/rebar/`](audit/rebar/README.md). ## Limits -- `Find` returns one leftmost match. Rebar's worst count-all row exposes a - multi-pattern plan that filters on common Cyrillic starts. The current plan - cannot combine rare interior pairs from several patterns. A measured one-pass - enumerator left that cost in place. See - [`REBAR.md`](REBAR.md) for the counters, profiles, and controls. -- Compiling a plan costs more than `strings.Index` on a single short lookup. -- AVX2 and scalar paths run the same correctness suite. The published lead - covers AVX-512, and there is no NEON kernel yet. -- Full-fold expansions such as `ß -> ss` are outside the relation. -- Adversarial data can leave many filter survivors. The arena includes - periodic, same-byte, and torture rows. Rebar contributes a Russian - multi-pattern example from a real corpus. - -## Map from the model to the code - -- [`plan.go`](plan.go) compiles fold tokens, the shared state machine, and every - conservative filter; it also contains the exact fallback transitions. -- [`matcher.go`](matcher.go) exposes the one-plan `Matcher` API. -- [`root_amd64.go`](root_amd64.go) performs runtime dispatch and connects plan - shapes to block transitions. +- The measured result covers Intel x86-64 with AVX-512F/BW/VBMI. +- AVX2 and scalar paths preserve semantics. They do not carry the published + speed claim. +- ARM64 uses the portable scalar path. There is no NEON kernel. +- The search relation is Unicode simple folding. Full-fold expansions are out + of scope. +- The API accepts literals and finite literal sets. +- Adversarial text can create many filter survivors. The arena includes + same-byte, periodic, torture, width-changing, dense-hit, and late-hit rows. + +## Map to the code + +- [`plan.go`](plan.go) compiles fold tokens, the shared state machine, and + route selection. +- [`unicode_confirm.go`](unicode_confirm.go) packs and checks fixed- and + variable-width raw confirmations. +- [`raw_byte.go`](raw_byte.go) builds tagged multi-pattern anchors and the + common-byte origin gate. +- [`matcher.go`](matcher.go) exposes `Find` and `Each` over the same plan. +- [`root_amd64.go`](root_amd64.go) performs runtime feature dispatch. - [`root_amd64.s`](root_amd64.s) contains the AVX2 and AVX-512 kernels. -- [`root_other.go`](root_other.go) is the portable implementation of the same - filter contracts. -- [`arena/field.yaml`](arena/field.yaml) defines who is allowed into the field - and what semantics and ISA each entrant ran. +- [`root_other.go`](root_other.go) implements the portable filter contracts. +- [`arena/field.yaml`](arena/field.yaml) defines the field, semantics, and + dispatch requirements. + +
diff --git a/NOVELTY.md b/NOVELTY.md index 25c480e..ffbafe9 100644 --- a/NOVELTY.md +++ b/NOVELTY.md @@ -1372,6 +1372,60 @@ the same compiled plan confirms its complete literal. The mixed-fold hit and miss arena rows, warmed per-pattern control, and Unicode / invalid-byte differentials are the operational falsifiers for these filters. +### Tagged interior-pair multi-anchor enumeration + +For an eligible multi-literal plan, the compiler assigns one pattern-tag bit to +each literal, chooses a stable interior UTF-8 pair as that literal's primary +anchor, and records a second pair at every possible bounded byte displacement +caused by earlier simple-fold spellings. A third pair is retained as an exact +scalar guard. The immutable plan owns a 64-entry first-byte table and +second-byte table for the primary tags, plus up to three corresponding +confirmation table pairs and their displacements. It is built with the search +plan, not from a caller, haystack sample, benchmark name, or first-use history. + +On a VBMI host, the block loop uses the low six bits of source bytes to look up +all primary and confirmation tag masks, intersects the masks for each compiled +displacement, and returns the first conservative survivor with its pattern-tag +byte. Exact full-byte primary, confirmation, and guard pairs are checked only +for those tags; low-six-bit aliases therefore cannot create a match. The shared +plan then replays the candidate and supplies byte start, source width, terminal +selection, leftmost order, and lowest-ID ties. Wider forms, malformed bytes, +unsupported plans, scalar tails, and feature-disabled hosts remain on the +existing decoded/raw-plan authority. This is a conservative enumeration filter, +not a separate recognizer or a byte-only fold definition. + +The components are known art: fixed rare anchors and candidate verification are +catalogued in `CONTEXT.md` §§3 and 8, while Vectorscan's Teddy implementation +uses compiled byte-class tables, `VPERMB`, and mask combination for the same +block-filter role. The repository-specific composition is a pattern-tagged, +variable-displacement set of UTF-8 interior-pair filters that retains the +shared fold-transition replay as the sole match authority. It makes no claim +that this state representation is new. Its operational claim is falsified by +any missed canonical reference occurrence, any disagreement between the +assembly predicate and its scalar table model, a tail-alignment failure, or a +full native field run that does not improve the contested result without +regressing another required row. + +### Variable-width raw confirmation + +An eligible N=1 Unicode plan now packs every one-, two-, or three-byte raw +spelling of each fold token into a bounded confirmation sequence. The pair-pair +screen fixes the candidate start only before the first width-changing orbit. +Confirmation then advances its cursor by the spelling that actually matched +and returns the resulting source width. `Matcher.Each` consumes that proved +width instead of decoding the same occurrence again. A malformed pattern, +four-byte spelling, orbit with more than three raw forms, oversized plan, or +unproved anchor retains the decoded executor. + +Raw candidate confirmation and finite fold-variant expansion are known art in +StringZilla, ClickHouse, Sneller, and the regex engines catalogued in +`CONTEXT.md`. The repository-specific packed layout and assembly loop encode +the existing plan's finite raw forms; they are not claimed as a new matching +state. Their operational result is new only if the same-contract field rows +move below 1.0 while differentials, exact source width, tails, and the complete +arena remain green. A bare shortest spelling at the end of a haystack is an +explicit regression case because it falsified the first maximum-width bound. + ### VBMI table and mask-scheduling follow-up The native Vectorscan 5.4.12 source prepared by `arena/vectorscan/prepare.sh` @@ -1400,13 +1454,219 @@ materializing a separate vector AND. The general pair-root loop separately unrolls two independent blocks after its first one-block probe, which is ordinary dependency/branch scheduling rather than a different matcher. -This is a negative novelty assessment. Byte-class table lookup, Teddy/Shufti -candidate masks, confirmation after a survivor, `VPERMB`/`VPERMT2B` selection, -and loop unrolling are established techniques. The package-specific table -layouts merely encode predicates the existing plan already owns, and the -common plan remains the sole match authority for N=1 and multi-pattern calls. -The only falsifiable claim is operational and belongs to the arena and semantic -differentials, not to a new search construction. +The tagged multi-anchor miss loop likewise carries four independent primary +blocks. Its retained schedule applies `VPTESTMB` directly to each pair of +pattern-tag vectors, retains the four k-masks, and crosses only the earliest +nonzero block into the scalar guard and shared-plan replay. Two aggregate +variants materialized all four products, OR-reduced them, and used one +`VPTESTMB` before reconstructing a block mask on a hit. The second also kept +the products across a false confirmation and checked all four blocks before +advancing, so it did not discard already computed primary work. Two pair- +retention variants instead kept the original primary pairs and k-masks, +materializing only the selected product after a false confirmation; one kept +pairs high and confirmation scratch low, while the other did the reverse. They +retained the direct no-hit instruction mix but increased live vector state +through the shared confirmation. All four regressed the real dense enumeration; +the product form also lost the raw N=5 miss A/B. They were removed. This +scheduling cell is reopened only by an alternating-order field run that +improves both the sparse synthetic rows and the real tagged enumeration without +changing the common-plan replay. + +The Vectorscan-derived software-prefetch detour is also closed. An +otherwise-identical `zero512` kernel issued one `PREFETCHT0` per 512-byte sparse +batch and was compared in same-process shuffled A/B runs at each lead distance: + +| `PREFETCHT0` lead | Result | Decision | +| --- | --- | --- | +| 512 bytes | Repeatedly slower | Removed | +| 1024 bytes | Neutral | Removed | +| 2048 bytes | Repeatedly slower | Removed | +| 4096 bytes | Repeatedly slower | Removed | + +The sweep targeted the common zero-only raw N=5 loop; no distance showed a +repeatable win, so no prefetch instruction remains and this dimension must not +be reopened without new evidence that changes the memory-latency premise. + +An AVX-512 BITALG union-scout variant was also rejected. It derived the union +of nonzero `second`-table classes once, broadcast its 64-bit membership mask, +and used eight memory-source `VPSHUFBITQMB` operations on the second-byte +windows at `1(AX), 65(AX), …, 449(AX)`. A zero union mask safely advanced 512 +bytes; a nonzero mask replayed the unchanged four-block tagged dispatcher. The +scalar model checked every low-six class and all four byte aliases, and the +assembly agreed with the vector table model across randomized horizons and +tails. The raw N=5 rows had a zero union mask in all 10,239 full chunks, while +Rebar always fell back, so the construction was reached on precisely the +intended sparse shape. + +Despite removing the explicit zero-scout loads, table lookups, products, and +vector reduction, four shuffled same-process Ice Lake A/B runs rejected it: + +| Workload | BITALG / retained median range | Result | +| --- | --- | --- | +| raw N=5 miss | 1.0014--1.0114 | Slower in every run | +| raw N=5 late hit | 1.0024--1.0157 | Slower in every run | +| dense-prefix/sparse-suffix | 1.0056--1.0181 | Slower in every run | +| uniform dense/no-confirm | 0.9834--1.0002 | Mixed, not a compensating gate | +| Rebar N=5 iterator | 0.9712--0.9818 | Faster, but insufficient against the raw regressions | + +The direct memory form assembled as intended and used no spills, but a +throughput reduction in one schedule does not establish a field improvement. +It was removed before a native field run because it failed the required +same-source raw and heterogeneous controls. Reopen it only with a materially +different membership/scheduling proof, not another tuning of this union scout. + +A separate zero512 Boolean-fusion cell was also rejected. The base materializes +eight primary tag products with `VPANDQ`, then OR-reduces them. The temporary +form used two four-block accumulators: one initial `VPANDQ` per accumulator, +three `VPTERNLOGD $0xf8` folds per accumulator, and one final `VPORQ`. +`0xf8` was modeled bit-for-bit as `dst | (srcA & srcB)` and the copied base and +fused kernels both matched the scalar vector-table model on randomized lengths, +tails, dense prefixes, and the Rebar enumeration checksum. Opcodex confirms +that the native Go-assembler `VPTERNLOGD` ZMM form needs only AVX-512F and is a +one-cycle, 0.5 reciprocal-throughput instruction on Ice Lake. + +Four pinned, shuffled same-process runs produced these fused/base paired-median +ranges: + +| Workload | Fused / base paired-median range | Result | +| --- | --- | --- | +| raw N=5 miss | 0.9957--1.0038 | Slower in three of four runs; no repeatable win | +| raw N=5 late hit | 0.9939--1.0011 | Mixed | +| dense-prefix/sparse-suffix | 0.9969--1.0037 | Mixed | +| Rebar N=5 iterator | 0.9976--1.0014 | Mixed | + +The lower Boolean instruction count did not yield repeatable sparse headroom +and did not clear the raw and heterogeneous gates. The fused source and copied +A/B kernel were removed without a native field run. Do not retry this exact +`0xf8` grouping; a future zero512 change needs a different bottleneck proof. + +Code-target alignment was assessed separately after that fusion result. The +unmodified zero512 target had low six address bits `0x13` in the test binary. +Temporary otherwise-identical kernels put `PCALIGN $32` or `PCALIGN +$64` immediately before that target; disassembly put each target at a +64-byte boundary. Both retained the predicate, confirmation horizon, density +switch, and raw-plan replay, and each agreed with the scalar table model and +Rebar's 971-result checksum. + +Four pinned, shuffled same-process runs gave these paired-median ranges versus +the unaligned kernel: + +| Workload | `PCALIGN $32` / base | `PCALIGN $64` / base | +| --- | --- | --- | +| raw N=5 miss | 0.9947--1.0032 | 0.9997--1.0049 | +| raw N=5 late hit | 0.9942--1.0056 | 0.9962--1.0021 | +| dense-prefix/sparse-suffix | 0.9986--1.0024 | 0.9977--1.0007 | +| Rebar N=5 iterator | 1.0179--1.0240 | 1.0201--1.0308 | + +Neither target had repeatable raw headroom, and both consistently regressed the +heterogeneous enumeration. The alignment copies were removed without a native +field run; do not reopen these target alignments absent a changed instruction +layout or a new bottleneck proof. + +A compiled universal-byte scout was also rejected after a source-level +min/max-width model. It intersected bytes invariant across every simple-fold +rendering of every eligible literal, selected space (`0x20`) for the five raw +N=5 literals, and converted each selected occurrence into the actual +primary-pair coordinate. The resulting package-owned interval was `[1,20]`; +it covered every compiled primary-start width and was admitted only when its +span was at most 64 bytes. A scalar combined model, randomized/tail checks, +width-changing forms, malformed bytes, endpoint lanes, and a deliberately +constructed low-six-bit tagged-table false positive all agreed with the +assembly and the existing exact replay. Disassembly showed the sparse path as +one early `VPCMPEQB` probe followed by eight memory-source `VPCMPEQB` probes +and k-mask OR reduction; a nonzero byte mask re-entered the unchanged tagged +four-block dispatcher. + +Four pinned, shuffled same-process A/B runs compared that scout with the same +compiled plan after only its valid bit was cleared: + +| Workload | Scout / no-scout paired-median range | Result | +| --- | --- | --- | +| raw N=5 miss | 0.9981--1.0095 | No repeatable gain | +| raw N=5 late hit | 1.0051--1.0099 | Slower in every run | +| dense-prefix/sparse-suffix | 1.0000--1.0139 | No gain; slower in three runs | +| Rebar N=5 iterator | 0.9561--0.9605 | Faster, but not a compensating gate | + +The sparse raw rows and heterogeneous control did not clear their gate, so the +universal compiler, vector path, model, and A/B harness were removed before a +native field run. Reopen this route only with a different instruction schedule +that improves both raw rows without losing the dense control; do not reuse the +same nine-probe layout. + +Changing level from the zero512 body to Find's origin also did not clear the +floor. A temporary compiler chose an ASCII byte fixed by `SimpleFold` that was +present in every literal, proved the maximum folded-source prefix width before +that byte, and used the existing `literalSkipASCII` scan to begin the unchanged +raw plan no later than that bound before the first occurrence. `literalSkipASCII` +was necessary rather than `rootSkipASCII`: the latter intentionally stops at a +high byte, while the exact fixed-byte predicate may skip UTF-8 and malformed +bytes. Enumerating every fold spelling before the selected byte, malformed +inputs, width-changing prefixes, unrelated earlier bytes, vector lanes/tails, +and tie cases all agreed with the reference matcher. + +Four pinned, shuffled same-process runs compared only this origin gate with the +same plan after its gate was disabled: + +| Workload | Origin gate / no-gate paired-median range | Result | +| --- | --- | --- | +| raw N=5 miss | 0.9957--1.0131 | Mixed; no repeatable gain | +| raw N=5 late hit | 0.9858--1.0037 | Mixed; no repeatable gain | + +The no-space miss still traversed the corpus once and reached the same +bandwidth/loop floor as zero512; the late-hit path likewise had no stable +advantage. The compiler, Find branch, and A/B tests were removed before a full +field run. Do not retry this exact origin gate without a different measured +reason it can beat that floor. + +### Retained origin proof with a dedicated exact scan + +The later retained path reuses the safe compiler fact from the rejected origin +experiment, but it does not reuse that transition. The rejected path called the +generic folded `literalSkipASCII` loop and did not move the raw miss floor. The +retained `literalSkipExact64` kernel exploits the stronger predicate: the +selected ASCII byte is invariant under `SimpleFold`, so it needs no fold vector. +It issues eight independent memory-source `VPCMPEQB` operations across 512 +bytes, retains their k-masks, and tests ordered mask pairs before extracting the +first lane. OpcodeX reports the relevant compare at three-cycle latency and +one-per-cycle reciprocal throughput on Ice Lake. Its uops.info catalog has no +Sapphire Rapids column, so the second host is supported by direct execution and +field measurement rather than that offline table. The scan then starts the +unchanged tagged plan no later than the maximum proved prefix before that first +exact byte. + +The gate ships only as part of the combined result with tagged survivor bits, +variable-width raw confirmation, and the wider sparse tagged schedule. No +isolated novelty claim is made for it. The combined source passed every sample +of the 36-row paired field on both hosts: worst medians were 0.9624 on Ice Lake +and 0.9716 on Sapphire Rapids. It also moved all five same-contract Rebar rows +below 1.0 on both hosts, with worst ratios 0.8794 and 0.8999. Those external +rows are the result the prior construction did not hold. + +The retained route is falsified by a missed fold spelling, a start earlier than +its lookback bound, a malformed-byte disagreement, a first-lane ordering error, +an assembly/model mismatch at any 64-byte boundary, any Rebar same-contract row +at or above 1.0, or any arena sample at or above 1.0. + +The checked-in [load-bearing ablations](audit/acceptance/ablations/README.md) +exercise those falsifiers. Removing the origin gate loses the focused N=5 +field row on both hosts. Removing variable confirmation loses two of five +same-contract Rebar rows on both hosts. Ignoring the returned tag byte loses +the five-pattern Rebar row on Ice Lake. + +### Novelty decision for the retained combination + +Byte-class table lookup, Teddy/Shufti candidate masks, fixed rare anchors, +confirmation after a survivor, `VPERMB`/`VPERMT2B` selection, finite fold-form +expansion, and loop unrolling are established techniques. The package-specific +tables encode predicates the existing plan already owns, and the common plan +remains the sole match authority for N=1 and multi-pattern calls. + +The construction is therefore a negative novelty finding at the component +level. The claimed advance is the result: correct simple-fold UTF-8 literal-set +search, including non-overlapping enumeration, that leads the complete pinned +field on all 36 arena rows and all five same-contract Rebar rows on both target +microarchitectures. A published implementation with the same semantics and a +better measured position would falsify that result claim. ### Complete experimental Go SIMD backend: negative result @@ -1445,7 +1705,7 @@ compiler already emits. This negative would be falsified by a later compiler/backend that preserves the four-way independent schedule, keeps mask arithmetic in k-registers, and avoids the wide spills, followed by a complete-backend result that passes the same -correctness checks and all 33 field rows on both qualifying processors. Until +correctness checks and all 36 field rows on both qualifying processors. Until then, the assembly backend remains the accepted implementation. ### Rejected cells @@ -1465,15 +1725,24 @@ Unicode/invalid-byte differential evidence. ## Provenance -This contribution contains novelty assessments and implementation provenance in this file. The -original orbit-quotient, raw-byte, fixed-width projection, rolling-fingerprint, -and prefix-invariant-anchor assessments, plus the five follow-up construction -sweeps above, were written for this repository from the current `AGENTS.md`, -`README.md`, `CONTEXT.md`, source and test files, and the cited source -locations. They contain no copied implementation code and make no external -performance claim. The follow-up sweep checked current upstream source via -`git ls-remote` and immutable raw-source revisions for GNU libc, .NET, -rust-lang/regex, Hyperscan, and StringZilla; semantic differences are stated -where those engines are used only as mechanical prior art. If implementation -files are added later, each non-trivial file will identify its authorship and -source provenance here. +This contribution contains novelty assessments and implementation provenance +in this file. The original orbit-quotient, raw-byte, fixed-width projection, +rolling-fingerprint, and prefix-invariant-anchor assessments, plus the follow-up +construction sweeps above, were written for this repository from the current +`AGENTS.md`, `README.md`, `CONTEXT.md`, source and test files, and the cited +source locations. + +The retained follow-up in `unicode_confirm.go`, `raw_byte.go`, `plan.go`, +`matcher.go`, `root_amd64.go`, `root_amd64.s`, `root_other.go`, the focused +arena rows, and their tests was produced in user-directed coding-agent sessions. +The public Perfloop Cases supplied experiment history and rejected hypotheses; +the final implementation was independently inspected, disassembled, modeled, +and measured in the repository workspace. OpcodeX from Perfloop commit +`ff4c454c6563852711156e7104f076529517c6c0` supplied offline instruction +latency and throughput data for the queried Intel targets. + +The implementation was written from the techniques, not copied from field +source. The follow-up read immutable source or built-object disassembly for +Vectorscan, PCRE2, rust/regex, StringZilla, veloz, and Rust Aho-Corasick. No +field implementation is imported, linked, executed, or embedded by the +candidate module; `scripts/check-baseline-isolation.sh` enforces that boundary. diff --git a/README.md b/README.md index 6372ee4..a8f681c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,89 @@ # casei -`casei` searches UTF-8 text without lowercasing it first. `IndexFold` finds one -literal. A compiled `Matcher` finds the leftmost of many literals in one scan. -Both use Unicode simple case folding, the same relation as Go's `regexp (?i)` -on valid UTF-8. Matches keep their original byte offsets, and the search never -builds a lowercased copy of the input. +Fast case-insensitive UTF-8 substring search for one literal or a whole set. + +`IndexFold` returns the byte offset of one literal. A compiled `Matcher` +returns the leftmost match from many literals in one scan. Both use Unicode +simple folding, the same case relation as Go's `regexp (?i)` on valid UTF-8. + +## The result + +On Intel Ice Lake and Sapphire Rapids with AVX-512F, BW, and VBMI, `casei` +finished first on every row of its 36-row arena. Each row includes the fastest +eligible result from Go regexp, PCRE2-JIT, rust/regex, Vectorscan, StringZilla, +veloz, and Rust Aho-Corasick where their contracts apply. + +| host | rows won | worst median `x_vs_best` | worst sample | median speedup | +|---|---:|---:|---:|---:| +| Ice Lake | 36/36 | 0.9624 | 0.9736 | 1.80× | +| Sapphire Rapids | 36/36 | 0.9716 | 0.9799 | 1.56× | + +`x_vs_best` is casei time divided by the fastest other implementation on the +same workload. Lower is better. Every one of the 216 measured row samples was +below 1.0. Every row had 5 to 7 entrants. `casei` reported 512-bit dispatch, +and Vectorscan reported a 512-bit VBMI database. + +Rebar provides a useful independent check. It asks engines to enumerate every +non-overlapping match instead of returning the first one. `casei` now wins all +five Rebar rows that request the same Unicode folding relation on both CPUs. + +| Rebar selection | Ice Lake | Sapphire Rapids | +|---|---:|---:| +| same Unicode contract | 5/5 wins, worst 0.8794 | 5/5 wins, worst 0.8999 | +| all 18 representable stress rows | 9/18 wins | 9/18 wins | + +The other 13 Rebar rows request ASCII-only case matching. `casei` keeps Unicode +simple-fold semantics on them, so those timings are published as stress data +rather than folded into the product claim. The complete table and raw receipts +are in [REBAR.md](REBAR.md). + +The speed claim is for the AVX-512 implementation. The portable implementation +is correct and scalar. There is no NEON kernel yet. + +## The idea + +Most of search is proving that a match does not start here. + +Imagine 64 possible starting positions in a block of text. `casei` checks a few +useful bytes for all 64 positions at once. The result is a 64-bit mask: + +```text +possible starts 0 1 2 3 4 5 ... 63 +first useful byte 0 0 1 0 0 0 ... 0 +second useful byte 0 0 1 0 1 0 ... 0 + -------------------- AND +survivors 0 0 1 0 0 0 ... 0 +``` + +An empty mask skips the whole block. A surviving bit means "check this one." +The exact Unicode plan checks it before `casei` can report a match. + +Compilation builds those two parts together: + +```text +patterns + | + +--> conservative byte sieve --> reject impossible starts in blocks + | + +--> exact simple-fold plan ----> decide matches, offsets, order, and ties +``` + +That is where the advantage comes from: + +1. The compiler knows the question is literal search under simple folding. It + can choose byte tests that a general regex engine cannot assume. +2. One pattern and 512 patterns use one compiled plan and one traversal. The + many-pattern sieve carries pattern tags, so exact replay checks only the + literals that survived. +3. Unicode decoding happens at survivors instead of at every byte. Width-changing + folds such as `k`/`K`/`K` are represented explicitly. +4. The AVX-512 kernels keep several independent blocks in flight and keep set + arithmetic in mask registers. The hand-written schedule matters: a complete + port to Go's experimental SIMD package stayed correct and lost the required + field row it was tested on. + +The [one-page explanation](HOW_IT_WORKS.md) follows this model into the actual +filters, assembly, competitor implementations, and measurements. ## Use it @@ -13,360 +92,143 @@ go get github.com/tsenart/casei ``` ```go -// One needle. Cache hits allocate nothing. +// One needle. if casei.ContainsFold(line, "payment declined") { - alert(line) + alert(line) } -// Byte offset instead of a bool. -at := casei.IndexFold(line, "payment declined") // -1 when absent +// Byte offset, or -1 when absent. +at := casei.IndexFold(line, "payment declined") -// Many needles, one pass. Leftmost match wins; ties go to the lowest -// pattern index. +// Many needles, one compiled plan. Leftmost match wins. A tie goes to the +// lowest pattern index. m := casei.NewMatcher([]string{"fatal panic", "oom killed", "segfault"}) if match, ok := m.Find(line); ok { - fmt.Println(m.Patterns()[match.Pattern], match.Start) + fmt.Println(m.Patterns()[match.Pattern], match.Start) } + +// Enumerate non-overlapping matches. Width is the number of source bytes +// consumed by this occurrence, which can differ across a Unicode fold orbit. +m.Each(log, func(match casei.Match, width int) bool { + fmt.Println(match.Pattern, match.Start, width) + return true +}) ``` -`NewMatcher` compiles the pattern set once. Reuse the `*Matcher` across searches -and share it freely; `Find` is safe for concurrent use. Every published -benchmark path allocates nothing after compilation, including cache-hit -`IndexFold`. Compiling a plan can allocate. During a search, the generic Unicode -plan allocates an offset ring only when its longest pattern needs more than the -256 entries kept inline. +`NewMatcher` compiles once. Reuse the matcher across searches. `Find` is safe +for concurrent use. Search is allocation-free on the published paths after +compilation. A generic plan with a longest pattern above the 256-entry inline +ring may allocate an offset ring during search. -On valid UTF-8, matching is Unicode **simple** case folding, identical to Go's -`regexp` with `(?i)`: `k` matches the Kelvin sign U+212A, `ſ` matches `s`, -`σ`/`ς`/`Σ` all match, and `ß` matches `ẞ` but never `ss`. Invalid bytes are -matched as opaque one-byte units. Lowercasing both sides does not have these -semantics. [Here is why](HOW_IT_WORKS.md#why-unicode-does-not-break-the-sieve). +The library requires Go 1.22 or newer. Rebuilding the native benchmark field +requires Go 1.24 or newer. -Requires Go 1.22+. The AVX-512 and AVX2 paths are chosen at runtime on x86-64; -every other platform runs the portable path, which returns identical results -(see [Limitations](#limitations) for what that costs). +## Semantics -## Where it stands +On valid UTF-8, matching follows Unicode simple folding: -On Intel Ice Lake and Sapphire Rapids with AVX-512F/BW/VBMI, `casei` finished -first on all 33 rows of its open arena. The median speedup over the fastest -correct alternative was 1.9x on Ice Lake and 1.6x on Sapphire Rapids. Those -rows cover first-match search and five single-needle count workloads. +- `k`, `K`, and Kelvin sign `K` match. +- `s`, `S`, and long s `ſ` match. +- `σ`, `ς`, and `Σ` match. +- `ß` and `ẞ` match. `ß` and `ss` do not. -Rebar asks a broader question: enumerate every non-overlapping match. On its -five rows with the same Unicode folding contract, `casei` wins two and loses -three on both hosts. +Invalid UTF-8 bytes are opaque one-byte units. Results use source byte offsets. +`Matcher.Find` returns the leftmost start, with ties resolved by the lowest +pattern index. `Matcher.Each` emits non-overlapping matches in that order and +returns the exact source width of each occurrence. -| measured question | Ice Lake | Sapphire Rapids | -|---|---:|---:| -| casei arena, 33 rows | 33/33 wins; 1.9x median lead | 33/33 wins; 1.6x median lead | -| Unicode-equivalent Rebar rows | 2/5 wins; worst loss 9.86x | 2/5 wins; worst loss 9.18x | +Correctness is checked against Go `regexp (?i)` by deterministic differential +tests and two fuzz targets. The portable path, AVX2 path, and AVX-512 path run +the same contract suite. Filter tests include exhaustive byte-pair projections, +randomized tails, malformed input, width-changing folds, and ordering ties. -This is the current boundary. The speed result covers x86-64 AVX-512 and the -arena's first-match and single-needle count contract. It does not claim -leadership for non-overlapping enumeration. The [Rebar audit](REBAR.md) records -every applicable workload, all six raw measurement passes, and the three -losses. +## How the field was measured -The Rebar result also found missing coverage in the original gym. Its -competitive bar had no multi-pattern enumeration row and none of Rebar's real -count/count-spans workloads. Perfloop optimized the board I supplied, so those -paths were not part of the original target. +The arena builds every native entrant from pinned source. It rejects an entrant +that silently dispatches below the width promised for that tier. Each row +reports active entrants and their observed vector widths. -### Work in progress +`BenchmarkBar` measures `casei` beside each eligible competitor six times. +The order alternates, so each operation goes first in three pairs. The median +paired ratio is computed for each competitor, and the largest ratio names the +fastest field result. The checked-in acceptance run repeats the complete board +three times on each host, pinned to one core. -Two newer public Cases carry the gap work forward: +The current raw transcripts are here: -- [Keep N=1 confirmation inside the AVX-512 scan](https://app.perfloop.ai/t/oss/case_s8c41a1per) - moved a new false-survivor row from `x_vs_best=4.547` to `0.7328` in ten - randomized pairs. [PR #10](https://github.com/tsenart/casei/pull/10) is open; - that targeted result has not yet passed the full two-host board. -- [Replace the decoded transition loop with one raw-byte plan](https://app.perfloop.ai/t/oss/case_rmg4fdm3me) - is the open general path for the remaining decoded-confirmation cost. +- [Ice Lake BenchmarkBar](audit/acceptance/results/ice/benchmarkbar.txt) +- [Sapphire Rapids BenchmarkBar](audit/acceptance/results/spr/benchmarkbar.txt) +- [Receipt verifier and summary](audit/acceptance/README.md) -The older hypotheses and their stopped results remain in the -[Rebar audit](REBAR.md#public-work-on-the-losses). A change is accepted only if -all five comparable Rebar rows win on both processors and every current -`BenchmarkBar` row remains below `x_vs_best=1.0` against the full-strength -field. +The repository also keeps the earlier sequential-window runs that exposed +measurement drift near parity. They failed the publication bar and are part of +the methodology record. -I built `casei` as a hard, self-contained test for -[Perfloop](https://app.perfloop.ai). I supplied the problem, constraints, -hypotheses, and reviews. Perfloop generated and measured the candidates. A -separate verifier tried to break each survivor. The -[full engine Case](https://app.perfloop.ai/t/oss/case_9r9ntnxjd1) is public. +To rebuild the field and rerun all 36 rows on a qualifying Linux host: -## How it gets its speed +```sh +./scripts/reproduce.sh +``` -A literal could start at every byte of the haystack. Checking the complete -Unicode relation at every byte is expensive, so `casei` first eliminates -starts with cheaper byte tests. +The script requires x86-64 with AVX2 and AVX-512F/BW/VBMI. It builds PCRE2, +Vectorscan, rust/regex, Rust Aho-Corasick, and StringZilla from their pinned +sources before it runs the board. -Compilation produces an exact plan and a set of cheaper byte tests: +## What changed after Rebar found the gap -```text -patterns -> complete simple-fold plan -> exact answer - \-> conservative byte filters -> 64 starts at once -> survivors only -``` +The original arena covered first-match search and single-needle counting. It +did not contain multi-pattern enumeration or the two focused shapes that made +Rebar's Russian rows hard. Perfloop optimized the board it was given. Rebar +showed what the board had omitted. -The AVX-512 sieve tests 64 possible starts together. On sparse workloads, most -blocks produce no survivors. A surviving bit means only “maybe,” so the exact -plan still decides Unicode equivalence, byte offsets, leftmost order, and -pattern ties. A filter may admit extra work, but it may never reject a real -match. - -The compiler chooses selective byte positions for the actual pattern set, and -shape-specific kernels evaluate them with 512-bit VBMI tables and mask -registers. One package-owned fold-token state machine handles both one needle -and many, so the fast path does not delegate to a second matcher. - -The assembly matters, but it amplifies the plan rather than replacing it. One -Shufti scheduling change improved its contested row by 21.8%. Bypassing the -shape-selected filters made the median row 3.88x slower on Ice Lake and 4.28x -slower on Sapphire Rapids. Replacing the complete backend with Go's -experimental SIMD package passed correctness and made a required field row -slower. - -[The one-page explanation](HOW_IT_WORKS.md) walks from that mental model to the -actual plan, kernels, competitor differences, causal measurements, and limits. - -## Results - -`BenchmarkBar` timed `casei` and every eligible competitor built from pinned -source in the same benchmark process, with each entrant dispatching its widest -eligible path. The complete tables below come from three fresh passes on each -GCP host, one exposing Ice Lake and one exposing Sapphire Rapids. Perfloop also -ran ten co-measured pairs of the pre-engine and final source, choosing the two -source arms' order randomly inside each pair; that public Case used the worst -`x_vs_best` across all 33 rows as its acceptance metric. - -Perfloop's verified runs put **casei first on every one of 33 rows, on both -microarchitectures**. The median speedup over the fastest correct alternative -was **1.9x** on Ice Lake and **1.6x** on Sapphire Rapids, using the median -`1 / x_vs_best` across the 33 acceptance rows. The narrowest median lead was -1.08x and the widest was 25.7x. The short table below comes from the separate -per-engine throughput lanes on Sapphire Rapids; both complete displays follow. -Throughput is in GB/s. Values are rounded to one decimal, so `0.0` means below -0.05 GB/s. `casei vs #2` uses those display lanes. - -| row | casei | Vectorscan | veloz | PCRE2-JIT | StringZilla | rust/regex | casei vs #2 | -|---|---|---|---|---|---|---|---| -| `log_miss_1mb` | **56.4** | 51.3 | 8.3 | 23.3 | 12.3 | 9.0 | **1.10×** | -| `code_miss_256kb` | **56.1** | 29.1 | 8.3 | 23.3 | 11.5 | 9.1 | **1.93×** | -| `prose_miss_1mb` | **56.3** | 19.5 | 8.3 | 23.2 | 12.1 | 9.0 | **2.43×** | -| `ru_miss_1mb` | **27.5** | 16.5 | – | 22.8 | 6.5 | 9.0 | **1.21×** | -| `multi_N512_miss_log_64kb` | **27.7** | 6.8 | – | 19.5 | 0.0 | 0.5 | **1.42×** | -| `multi_N512_miss_hazard_64kb` | **9.8** | 4.6 | – | 0.0 | 0.0 | 0.5 | **2.14×** | -| `latency_match_start_1kb` | **118.1** | 2.9 | 70.1 | 4.6 | 4.4 | 3.3 | **1.68×** | -| `samechar_miss_64kb` | **67.6** | 44.7 | 8.3 | 22.3 | 11.0 | 0.5 | **1.51×** | -| `periodic_miss_64kb` | **35.5** | 0.6 | 8.3 | 28.4 | 11.0 | 0.5 | **1.25×** | -| `torture_miss_64kb` | **13.1** | 0.1 | 0.5 | 0.3 | 0.1 | 0.3 | **25.76×** | -| `log_hit_sparse_1mb` | **32.1** | 1.5 | 8.0 | 7.2 | 10.3 | 6.6 | **3.11×** | - -
-Full 33-row tables for both CPUs - -The visible columns show the six engines with lanes on all or most rows; -`rust/regex` is the rure adapter. Go `regexp` and Rust Aho-Corasick are omitted -from this display. Both still enter the acceptance row's `x_vs_best` wherever -eligible. The display ratio and acceptance score are kept separate because -they come from different benchmark surfaces. - -#### Sapphire Rapids (Xeon 8481C), GB/s (higher is better; **bold** = casei) - -| row | casei | Vectorscan | veloz | PCRE2-JIT | StringZilla | rust/regex | casei vs #2 | -|---|---|---|---|---|---|---|---| -| `latency_match_start_1kb` | **118.1** | 2.9 | 70.1 | 4.6 | 4.4 | 3.3 | **1.68×** | -| `samechar_miss_64kb` | **67.6** | 44.7 | 8.3 | 22.3 | 11.0 | 0.5 | **1.51×** | -| `log_miss_1mb` | **56.4** | 51.3 | 8.3 | 23.3 | 12.3 | 9.0 | **1.10×** | -| `prose_miss_1mb` | **56.3** | 19.5 | 8.3 | 23.2 | 12.1 | 9.0 | **2.43×** | -| `code_miss_256kb` | **56.1** | 29.1 | 8.3 | 23.3 | 11.5 | 9.1 | **1.93×** | -| `log_miss_64kb` | **53.4** | 45.2 | 8.3 | 22.3 | 12.3 | 8.9 | **1.18×** | -| `log_needle3_64kb` | **53.3** | 45.0 | 8.3 | 22.1 | 18.0 | 13.8 | **1.19×** | -| `log_needle32_64kb` | **53.3** | 6.8 | 8.3 | 21.0 | 11.0 | 8.9 | **2.54×** | -| `log_needle16_64kb` | **53.3** | 36.0 | 8.3 | 22.1 | 11.8 | 8.9 | **1.48×** | -| `log_needle8_64kb` | **53.0** | 6.8 | 8.3 | 20.9 | 18.0 | 8.9 | **2.53×** | -| `multi_N8_miss_ru_1mb` | **38.6** | 5.7 | – | 23.3 | 0.8 | 9.0 | **1.66×** | -| `multi_N64_miss_ru_64kb` | **37.0** | 7.2 | – | 21.8 | 0.1 | 0.5 | **1.70×** | -| `multi_N8_hazard_hit_1mb` | **35.5** | 6.7 | – | 2.7 | 0.9 | 31.6 | **1.13×** | -| `periodic_miss_64kb` | **35.5** | 0.6 | 8.3 | 28.4 | 11.0 | 0.5 | **1.25×** | -| `log_hit_sparse_1mb` | **32.1** | 1.5 | 8.0 | 7.2 | 10.3 | 6.6 | **3.11×** | -| `multi_N8_miss_log_1mb` | **29.3** | 6.8 | – | 14.3 | 1.6 | 9.0 | **2.04×** | -| `multi_N64_miss_log_64kb` | **27.7** | 6.8 | – | 22.0 | 0.2 | 0.5 | **1.26×** | -| `multi_N512_miss_log_64kb` | **27.7** | 6.8 | – | 19.5 | 0.0 | 0.5 | **1.42×** | -| `ru_miss_1mb` | **27.5** | 16.5 | – | 22.8 | 6.5 | 9.0 | **1.21×** | -| `ru_hit_sparse_1mb` | **24.5** | 0.8 | – | 19.3 | 6.5 | 8.5 | **1.27×** | -| `latency_match_mid_1kb` | **22.7** | 2.4 | 14.5 | 2.6 | 3.8 | 2.5 | **1.57×** | -| `kelvin_hazard_1mb` | **20.3** | 1.8 | – | 1.2 | 12.8 | 8.5 | **1.58×** | -| `multi_N8_miss_hazard_1mb` | **18.3** | 6.8 | – | 0.3 | 0.9 | 2.8 | **2.67×** | -| `multi_N2_miss_log_1mb` | **15.2** | 11.5 | – | 0.7 | 5.8 | 5.5 | **1.32×** | -| `log_miss_1kb` | **13.7** | 5.5 | 7.9 | 5.4 | 5.5 | 4.0 | **1.74×** | -| `latency_match_end_1kb` | **13.5** | 2.4 | 7.5 | 1.7 | 3.2 | 2.0 | **1.80×** | -| `latency_miss_1kb` | **13.4** | 4.6 | 7.9 | 4.9 | 5.4 | 3.9 | **1.69×** | -| `prose_hit_dense_1mb` | **13.1** | 0.0 | 6.8 | 1.0 | 4.2 | 2.9 | **1.93×** | -| `torture_miss_64kb` | **13.1** | 0.1 | 0.5 | 0.3 | 0.1 | 0.3 | **25.76×** | -| `code_hit_brackets_256kb` | **11.1** | 0.0 | 6.0 | 1.1 | 1.3 | 0.9 | **1.86×** | -| `multi_N8_hit_log_1mb` | **10.2** | 5.7 | – | 2.0 | 1.8 | 2.5 | **1.78×** | -| `multi_N512_miss_hazard_64kb` | **9.8** | 4.6 | – | 0.0 | 0.0 | 0.5 | **2.14×** | -| `ru_latency_miss_1kb` | **8.5** | 3.6 | – | 5.1 | 3.9 | 3.6 | **1.65×** | - -#### Ice Lake (Xeon @ 2.6 GHz), GB/s (higher is better; **bold** = casei) - -| row | casei | Vectorscan | veloz | PCRE2-JIT | StringZilla | rust/regex | casei vs #2 | -|---|---|---|---|---|---|---|---| -| `latency_match_start_1kb` | **118.2** | 2.5 | 63.6 | 4.2 | 3.7 | 3.1 | **1.86×** | -| `samechar_miss_64kb` | **71.7** | 39.0 | 6.9 | 22.7 | 11.0 | 0.6 | **1.84×** | -| `prose_miss_1mb` | **57.2** | 16.7 | 6.8 | 16.4 | 12.2 | 9.5 | **3.43×** | -| `log_miss_1mb` | **57.1** | 45.0 | 6.8 | 21.8 | 12.2 | 9.4 | **1.27×** | -| `code_miss_256kb` | **56.9** | 23.1 | 6.9 | 19.1 | 11.5 | 9.6 | **2.47×** | -| `log_miss_64kb` | **54.5** | 38.9 | 6.8 | 19.8 | 11.9 | 9.3 | **1.40×** | -| `log_needle32_64kb` | **52.8** | 6.9 | 6.9 | 16.0 | 11.0 | 9.4 | **3.31×** | -| `log_needle8_64kb` | **52.8** | 6.9 | 6.9 | 16.1 | 15.5 | 9.2 | **3.28×** | -| `log_needle16_64kb` | **52.8** | 28.2 | 6.9 | 15.8 | 11.7 | 9.3 | **1.87×** | -| `log_needle3_64kb` | **52.6** | 38.9 | 6.9 | 16.5 | 15.3 | 14.3 | **1.35×** | -| `multi_N8_miss_ru_1mb` | **37.0** | 6.1 | – | 16.5 | 0.8 | 9.5 | **2.24×** | -| `multi_N8_hazard_hit_1mb` | **35.4** | 7.7 | – | 3.0 | 1.0 | 33.0 | **1.07×** | -| `multi_N64_miss_ru_64kb` | **35.2** | 5.8 | – | 15.7 | 0.1 | 0.5 | **2.24×** | -| `multi_N8_miss_log_1mb` | **31.1** | 7.0 | – | 13.3 | 1.6 | 9.5 | **2.33×** | -| `periodic_miss_64kb` | **30.9** | 0.5 | 6.9 | 23.5 | 11.0 | 0.6 | **1.32×** | -| `multi_N64_miss_log_64kb` | **29.5** | 6.9 | – | 20.4 | 0.2 | 0.5 | **1.45×** | -| `multi_N512_miss_log_64kb` | **29.5** | 6.9 | – | 13.8 | 0.0 | 0.5 | **2.13×** | -| `log_hit_sparse_1mb` | **27.6** | 1.5 | 6.7 | 6.9 | 10.3 | 6.8 | **2.67×** | -| `ru_miss_1mb` | **21.7** | 17.4 | – | 16.4 | 6.4 | 9.6 | **1.25×** | -| `kelvin_hazard_1mb` | **21.0** | 1.9 | – | 1.1 | 12.3 | 8.9 | **1.70×** | -| `multi_N8_miss_hazard_1mb` | **18.5** | 7.5 | – | 0.3 | 0.9 | 3.1 | **2.46×** | -| `latency_match_mid_1kb` | **18.5** | 2.0 | 12.0 | 2.3 | 3.2 | 2.4 | **1.54×** | -| `ru_hit_sparse_1mb` | **18.3** | 0.9 | – | 16.0 | 6.2 | 8.8 | **1.15×** | -| `multi_N2_miss_log_1mb` | **15.0** | 11.6 | – | 0.7 | 5.9 | 5.8 | **1.29×** | -| `log_miss_1kb` | **13.3** | 4.4 | 6.6 | 4.6 | 4.8 | 3.6 | **2.03×** | -| `latency_miss_1kb` | **12.8** | 3.8 | 6.6 | 4.2 | 4.7 | 3.6 | **1.95×** | -| `prose_hit_dense_1mb` | **12.0** | 0.0 | 5.8 | 1.0 | 3.6 | 2.8 | **2.06×** | -| `latency_match_end_1kb` | **11.0** | 2.0 | 6.2 | 1.6 | 2.9 | 2.0 | **1.79×** | -| `torture_miss_64kb` | **10.2** | 0.1 | 0.4 | 0.2 | 0.1 | 0.3 | **25.51×** | -| `multi_N8_hit_log_1mb` | **10.1** | 5.9 | – | 1.9 | 1.7 | 2.8 | **1.71×** | -| `multi_N512_miss_hazard_64kb` | **9.8** | 3.9 | – | 0.0 | 0.0 | 0.5 | **2.53×** | -| `code_hit_brackets_256kb` | **9.1** | 0.0 | 5.0 | 1.0 | 1.1 | 0.7 | **1.82×** | -| `ru_latency_miss_1kb` | **8.0** | 3.1 | – | 4.6 | 3.5 | 3.4 | **1.74×** | - -Diagnostic baselines (`ToLower`+`Index`, the Go Aho-Corasick port, and the -exact-match `ceiling`) are omitted from the “fastest” comparison. The -[methodology](#benchmark-method) explains why. Rebuild the field and rerun the -local board with `./scripts/reproduce.sh`. -
- -The 33 rows include 28 first-match operations and five overlap-allowed -single-needle count operations. They cover ASCII and UTF-8 workloads, with one -needle or many, on both processors. Vectorscan used its 512-bit AVX-512 VBMI -path on the same machines. This gives the field an equal-width control alongside -narrower engines such as AVX2 veloz and 128-bit PCRE2-JIT. Every benchmark row -reports the width each entrant used. - -Rebar measures non-overlapping `count` and `count-spans`. On the five -performance rows that share `casei`'s Unicode contract, the loop-over-`Find` -adapter wins two and loses three on both hosts. The worst row spends its time -behind a weak shared filter choice; a stateful enumerator left that cost in -place. The [complete Rebar audit](REBAR.md) lists every applicable row, the -original benchmark coverage gap, and the controls used to trace the losses. - -On valid UTF-8, correctness is pinned to Go `regexp` `(?i)` by deterministic -single- and multi-pattern differentials. The suite runs under both x86 vector -paths. The portable scalar dispatch runs it too. It includes tens of thousands -of randomized searches and two exhaustive 65,536-pair filter checks. -`FuzzIndexFold` and `FuzzMatcher` run separately. Invalid-byte inputs are checked -against the opaque-unit contract. - -## Reproduce it - -With Go 1.24+ on an x86-64 Linux host **with AVX2 and AVX-512F/BW/VBMI** (pin a -GCP `n2` to Ice Lake, use `c3` for Sapphire Rapids, or use equivalent recent -Intel hardware), one script builds the entire competitor field from source and -runs the scoreboard. Apple Silicon does not meet this performance-host -contract. CI rebuilds and checks the same pinned field for correctness on every -push. +The follow-up added three focused arena rows and kept the Rebar rows as an +external gate. The surviving construction combines: -```sh -git clone https://github.com/tsenart/casei && cd casei -./scripts/reproduce.sh # ~15 min: builds pcre2, vectorscan (VBMI), rure, - # rust-regex, stringzilla, then runs the benchmark -``` +- tagged interior anchors for several Unicode literals; +- raw confirmation that follows one-, two-, and three-byte fold spellings and + returns the source width it proved; +- an exact common-byte origin gate for eligible multi-pattern plans; and +- wider assembly schedules that scan several cache lines before testing masks. + +The result closes all five same-contract Rebar rows while preserving all 36 +arena wins. [REBAR.md](REBAR.md) contains the before/after account and every +external row. -It prints, for all 33 rows, every entrant's local throughput and the vector -width it dispatched, plus `x_vs_best` (`casei`'s time ÷ the fastest *correct* -competitor). It then fails unless all three samples of every row are below 1, -every row has at least two entrants, and both `casei` and Vectorscan report -512-bit dispatch with Vectorscan's VBMI path active. Perfloop's public Case -separately records ten co-measured pre-engine/final-source pairs, with random -source-arm order, for the board's worst `x_vs_best`. - -The [publication audit](audit/publication/README.md) records a fresh three-pass -acceptance run on both CPU models, the work-avoidance and AVX-512 ablations, -raw samples, and the script that recomputes their summaries. - -## Benchmark method - -
-Read the field, scoring, and measurement rules - -The arena applies the following rules: - -- A baseline enters `x_vs_best` after its output passes the agreement tests for - that tier. `ToLower` plus `Index` and the Go Aho-Corasick port remain - diagnostic lanes. -- Each row is scored against its fastest eligible competitor. -- Entrants report the ISA and vector width they dispatched. Vectorscan is built - with `BUILD_AVX512VBMI`, and the arena checks that its 512-bit path ran. -- The workload set includes `periodic`, `samechar`, and `torture` inputs that - expose data-dependent cliffs. -- Twenty-eight rows measure a first byte offset or a leftmost match with ties - resolved by pattern order. Five single-needle rows repeatedly request the - first offset and count every overlap-allowed match. An entrant with an - enumeration API performs the required reduction inside its timed operation. -- [`arena/field.yaml`](arena/field.yaml) pins nine engines to source versions - and build flags. Perfloop's engine Case records ten co-measured source pairs. - `reproduce.sh` rebuilds the field and runs the local board. - -I wrote the arena alongside `casei`. Its source, workloads, field manifest, and -measurements are open for independent runs. - -
- -## Limitations - -- The measured performance result covers AVX-512. Other x86 machines use the - AVX2 path. ARM uses the portable scalar path, with no NEON kernel yet. All - three dispatch modes run the correctness suite. -- `NewMatcher` is meant to be reused. On a tiny one-shot lookup, plan setup - gives `strings.Index` the advantage. -- The contract is Unicode simple folding. Full-fold expansions such as - `ß` to `ss` are outside it. -- The public API returns the first match. The rebar adapter enumerates by - calling `Find` again on each suffix and loses three of five comparable rows - on both measured hosts. [`REBAR.md`](REBAR.md) includes those results and the - ASCII-only rows that ask for weaker folding semantics. - -## How it was built - -I used `casei` as an operator-directed Perfloop case. I supplied the hypotheses -and audited the field and host ISA; Perfloop generated candidates and killed or -kept them by measurement. The public trails cover the -[engine](https://app.perfloop.ai/t/oss/case_9r9ntnxjd1) and a later -[kernel-scheduling refinement](https://app.perfloop.ai/t/oss/case_hqryrfd6j4). -The Rebar audit then widened the gym and exposed the three open losses above. -The repository contains the resulting source, field manifest, correctness -tests, measurements, and reproduction scripts. - -## Details - -- [`HOW_IT_WORKS.md`](HOW_IT_WORKS.md): the short mental model first, followed - by the exact plan, assembly contribution, competitor comparison, and - evidence. -- [`REBAR.md`](REBAR.md): every applicable third-party rebar workload, the - semantic map, both-host measurements, real losses, and their diagnosis. -- [`arena/field.yaml`](arena/field.yaml): the field, versions, build flags, - ISA, corpus hashes, semantic status. -- [`CONTEXT.md`](CONTEXT.md): every technique known to this problem, with - sources and measured numbers (including rebar's published results). -- [`NOVELTY.md`](NOVELTY.md): the construction and prior-art assessment; the fold-orbit - representation is *not* claimed as novel, and says why. -- [`AGENTS.md`](AGENTS.md): the arena's rules of engagement, baseline isolation, - single-engine identity, and the acceptance bar a candidate must clear. +## Perfloop record + +I built `casei` as a hard, self-contained test for +[Perfloop](https://app.perfloop.ai). I supplied the problem, field, and +constraints. Perfloop proposed implementations, measured them against the +field, and sent survivors to an independent verifier. + +- [Original full-engine Case](https://app.perfloop.ai/t/oss/case_9r9ntnxjd1) +- [Shared interior-anchor Case](https://app.perfloop.ai/t/oss/case_jws72csfa9) +- [Dispersed Unicode-probe Case](https://app.perfloop.ai/t/oss/case_b2m0dmh5wa) +- [Raw-confirmation Case](https://app.perfloop.ai/t/oss/case_tgkp9bs0r6) +- [Complete Go SIMD backend, rejected](https://app.perfloop.ai/t/oss/case_37sjyc8f94) + +The public Cases are the experiment log. [`NOVELTY.md`](NOVELTY.md) records +the constructions that failed on paper or in measurements. Negative results +stay in the repo so the next attempt starts from evidence. + +## Limits + +- Published speed numbers cover x86-64 AVX-512F/BW/VBMI on Intel Ice Lake and + Sapphire Rapids. +- The portable path is scalar. ARM64 is correct, with no NEON speed claim. +- The API searches literals and finite literal sets. +- Folding is Unicode simple folding. Full-fold expansions such as `ß -> ss` + are outside the contract. +- Plan compilation has a cost. Cache a matcher for repeated searches. +- The 36-row arena belongs to this repository. Its sources, field, dispatch, + failed measurements, and verifier are open and pinned. Rebar is the external + cross-check. + +## Read next + +- [How it works](HOW_IT_WORKS.md) +- [Direct Rebar audit](REBAR.md) +- [Known field and prior art](CONTEXT.md) +- [Novelty and negative results](NOVELTY.md) +- [Current acceptance receipts](audit/acceptance/README.md) +- [Rebar receipts](audit/rebar/README.md) diff --git a/REBAR.md b/REBAR.md index 2d16810..a01f9bc 100644 --- a/REBAR.md +++ b/REBAR.md @@ -1,251 +1,205 @@ # Direct Rebar audit -`casei` loses three of the five Rebar workloads that ask the same Unicode -folding question. Rebar counts every non-overlapping match. The 33-row arena -contains 28 first-match operations and five overlap-allowed single-needle -counts. It has no multi-pattern enumeration row. On Rebar's worst row, a weak -multi-pattern filter sends too much text into the exact Unicode plan. A measured -streaming version left that cost in place. - -The audit below includes every caseless literal or finite-alternation workload -that `casei` can represent. +Rebar found the hole in the original `casei` benchmark. It also provides the +external check that the hole is now closed. ## The answer in 30 seconds At Rebar commit [`463d00f`](https://github.com/BurntSushi/rebar/commit/463d00f31887e84c38467805b9e3122c314b9521), -the inventory contains 18 performance workloads and three behavior checks. -`casei` passed the two checks that use compatible Unicode semantics. The third -asks `s` to miss `ſ`, which conflicts with Unicode simple folding. - -Only five performance rows enable Unicode semantics and therefore ask the same -folding question as `casei`. Against Rebar's three recorded leaders (Hyperscan, -PCRE2-JIT, and rust/regex), `casei` wins **2/5** and loses **3/5** on both Ice Lake -and Sapphire Rapids. Its median `time / best-other-time` is 1.27 and 1.28; the -worst row is roughly 9× slower. - -The remaining 13 performance rows request ASCII-only case insensitivity. -`casei` produced the expected answers on those corpora while retaining its -stronger Unicode relation. Their timings remain useful as stress tests under -that contract. - -## Why the original gym missed these losses - -The arena's scenario list had five single-needle count rows during the original -engine build. Its competitive bar mistakenly ignored their `count` flag and -timed only the first match. Commit -[`c4392e7`](https://github.com/tsenart/casei/commit/c4392e7e6bbdaa8cd263059d5a041b29bd57e9ae) -corrected that wiring before the publication runs. `casei` won those five rows -in the corrected 33-row result. - -The corrected arena still counts by repeatedly calling a single-needle search. -It has no row that enumerates a compiled multi-pattern plan, and its synthetic -Unicode count rows do not cover the dense Russian corpus or the Rebar prefilter -shape measured here. The original Perfloop objective never asked it to win on -these paths. - -The missing coverage let the losses survive. The measurements below identify -their direct causes: weak shared filtering on the five-pattern row and costly -native confirmation on the two single-pattern rows. The 33 arena rows remain -regression gates, and the five Unicode-equivalent Rebar rows are the acceptance -target for the open work. - -## Why this is a different benchmark contract - -| | casei arena | Rebar rows on this page | -|---|---|---| -| answer | first byte offset or leftmost match on 28 rows; overlap-allowed count on 5 single-needle rows | count or total span of every non-overlapping match | -| search state | one `IndexFold`/`Find` call, repeated from the next byte on the 5 count rows | one compiled engine repeatedly enumerates from the end of each match | -| pattern sets | multi-pattern rows stop at the first leftmost answer | both single-pattern and multi-pattern rows enumerate to the end | -| folding | Unicode simple folding on every row | Unicode on 5 rows, ASCII-only on 13 | -| measurement | in-process field timing, with three publication passes on each pinned host; Perfloop separately co-measured the engine's source revisions | [Rebar's sequential runner protocol](https://github.com/BurntSushi/rebar/blob/463d00f31887e84c38467805b9e3122c314b9521/METHODOLOGY.md), three independent passes here | +18 performance workloads can be represented as one literal or a finite set of +literals. Five request Unicode-aware case folding and ask the same semantic +question as `casei`. -The audit adapter compiles `NewMatcher` outside the timed region. Each iteration -calls `Find` on successive suffixes until it reaches the end. The adapter checks -the matched byte width under simple folding before advancing. It supports -rebar's `count` and `count-spans` models, with the same compiled plan reused for -every hit. A future iterator could retain scan state and vector continuity. The -diagnosis below measures how much that would change the worst row. +`casei` now wins all five on both measured CPUs: -## Results +| host | wins | median `casei / best` | worst row | +|---|---:|---:|---:| +| Ice Lake | 5/5 | 0.6441 | 0.8794 | +| Sapphire Rapids | 5/5 | 0.6716 | 0.8999 | -`casei / best` is median casei time divided by the fastest selected competitor -on the same row and pass, then the median across three passes. Values below 1.0 -are wins. The named competitor is the fastest by its three-pass median. +Values below 1.0 are wins. The selected field is Hyperscan 5.4.2, PCRE2 10.47 +JIT, and rust/regex 1.12.4. -| rebar row | requested folding | Ice Lake `casei / best` | Sapphire Rapids `casei / best` | -|---|---|---:|---:| -| `curated/01-literal/sherlock-casei-en` | ASCII-only* | 7.57× (Hyperscan) | 8.88× (Hyperscan) | -| `curated/01-literal/sherlock-casei-ru` | Unicode | 2.57× (PCRE2-JIT) | 2.47× (PCRE2-JIT) | -| `curated/02-literal-alternate/sherlock-casei-en` | ASCII-only* | 7.02× (Hyperscan) | 7.02× (Hyperscan) | -| `curated/02-literal-alternate/sherlock-casei-ru` | Unicode | 9.86× (Hyperscan) | 9.18× (Hyperscan) | -| `hyperscan/literal-casei-english-nosom` | ASCII-only* | 4.95× (Hyperscan) | 6.40× (Hyperscan) | -| `hyperscan/literal-casei-english-som` | ASCII-only* | 4.96× (Hyperscan) | 6.52× (Hyperscan) | -| `hyperscan/literal-casei-russian-nosom` | Unicode | **0.71×** (rust/regex) | **0.58×** (rust/regex) | -| `hyperscan/literal-casei-russian-som` | Unicode | **0.72×** (rust/regex) | **0.56×** (rust/regex) | -| `imported/leipzig/tom-sawyer-huckle-fin-insensitive` | ASCII-only* | 2.70× (Hyperscan) | 3.10× (Hyperscan) | -| `imported/leipzig/twain-insensitive` | ASCII-only* | 1.35× (Hyperscan) | 1.18× (Hyperscan) | -| `imported/sherlock/name-alt3-casei` | ASCII-only* | **0.78×** (rust/regex) | **0.69×** (rust/regex) | -| `imported/sherlock/name-alt5-casei` | ASCII-only* | 1.04× (rust/regex) | **0.94×** (rust/regex) | -| `imported/sherlock/name-holmes-casei` | ASCII-only* | **0.79×** (PCRE2-JIT) | **0.75×** (PCRE2-JIT) | -| `imported/sherlock/name-sherlock-casei` | ASCII-only* | 1.57× (PCRE2-JIT) | 1.82× (PCRE2-JIT) | -| `imported/sherlock/name-sherlock-holmes-casei` | ASCII-only* | 2.64× (PCRE2-JIT) | 3.04× (PCRE2-JIT) | -| `imported/sherlock/the-casei` | ASCII-only* | 1.08× (PCRE2-JIT) | **0.90×** (PCRE2-JIT) | -| `opt/prefilter/literal-casei-english` | ASCII-only* | 1.85× (PCRE2-JIT) | 2.22× (PCRE2-JIT) | -| `opt/prefilter/literal-casei-russian` | Unicode | 1.27× (PCRE2-JIT) | 1.28× (PCRE2-JIT) | - -`*` Rebar disables Unicode-aware case folding. `casei` cannot disable it, so it -does more work and would also match Unicode fold mates not present in these -particular corpora. These rows passed output verification on the recorded text. -Their requested relation is ASCII-only, so they stay outside the -contract-equivalent result. - -Across all 18 stress rows, including those ASCII-only rows, `casei` wins 4/18 -on Ice Lake and 6/18 on Sapphire Rapids. The product comparison uses the five -rows with the same Unicode contract. - -## Why the worst row is 9× slower - -The bad row searches a 1,570,556-byte Russian Sherlock Holmes corpus for five -names and counts 971 matches: +The remaining 13 rows request ASCII-only case matching. `casei` keeps its +Unicode relation and does more work. Across all 18 stress rows it wins 9/18 on +each host. All rows and losses appear below. + +## Before and after + +The first Rebar audit was bad for `casei`: + +```text +before + +five Russian patterns + | + v +common first-byte filter -> too many survivors -> decoded Unicode replay + | + +----------------------------------------> about 9x behind Hyperscan + +one Russian pattern + | + v +good interior anchor -> survivor -> decoded Unicode replay + | + +----------> behind native confirmation +``` + +The accepted follow-up keeps one plan and changes the work before replay: ```text -one Russian pattern rare interior byte pairs -> about 2,100 candidates -five Russian patterns common starting letters -> about 80,000 filter stops +after + +five Russian patterns + | + +-> exact shared-byte origin gate + +-> tagged interior pairs for each literal + +-> exact pair checks for surviving tags + +-> the same raw fold-token plan ----------------------> 0.84x to 0.88x + +one Russian pattern + | + +-> pair-pair screen + +-> raw one/two/three-byte fold confirmation + +-> confirmed source width ----------------------------> 0.29x to 0.90x ``` -For one pattern, the compiler selects a fused pair-pair anchor from inside the -literal. The AVX-512 VBMI kernel skips 1,552,007 bytes and asks the exact -matcher to check 2,134 candidate positions. - -For all five patterns, the current compiler cannot combine those interior -anchors into one shared filter. It falls back to a nine-pair Shufti filter over -the patterns' first UTF-8 bytes. Several of those starts are common Cyrillic -letters. Across the full count, the filter is invoked 79,950 times and admits -193,449 runes, or 21.7% of the corpus, into the exact plan. The plan performs -175,860 dense state transitions. The CPU profile attributes most of the time to -UTF-8 decoding and fold-token map lookup. The AVX-512 filter is a smaller part -of the row. - -A one-pass diagnostic enumerator took 4.69 ms, compared with 4.65 to 4.99 ms for -repeated `Find`. Both returned 971 matches. The API restart cost is within the -noise on this row. - -Replacing Shufti with the exact nine-pair AVX-512 filter made the row slower. -Disabling AVX-512 added roughly 25% to 33%. Those measurements put the cost in -the selectivity of the compiled question reaching the kernel. - -Rebar's Hyperscan runner was rebuilt and checked independently. It returned 971 -matches with an AVX-512 VBMI database. Start-of-match tracking changed its time -by about 2%. Hyperscan expands the folds at compile time into a byte-level -database and scans the five literals continuously. Its verification path avoids -the Go rune decoder and token map used here. - -The smaller two losses have the same general shape at lower severity. On the -single Russian literal, `casei`'s rare interior anchor is effective. Each -survivor still enters a Go rune decoder and token map. PCRE2-JIT verifies in -native code and leads by about 2.5×. On the sparse one-match Russian prefilter -row, that residual verification gap is about 1.28×. The two wins compare the -same sparse shape with rust/regex. +The multi-pattern screen returns pattern tags, not matches. The existing plan +still decides every result. The variable-width confirmer returns the number of +source bytes it proved, so `Matcher.Each` can continue without decoding that +match again. + +The common-byte gate applies only when every simple-fold spelling of every +literal contains the same exact ASCII byte. It proves the latest possible +start before the first occurrence. Its AVX-512 kernel compares eight cache +lines before testing the ordered masks. If the proof cannot be compiled, the +route is absent. + +## Why the original gym missed it + +The original arena had first-match rows and five single-needle count rows. The +competitive bar once ignored the count flag on those five rows and timed only +the first match. That wiring was corrected before the earlier publication run, +and `casei` won the corrected rows. + +Two gaps remained: + +1. No row enumerated a compiled multi-pattern Unicode plan to the end of a + corpus. +2. No focused row forced variable-width confirmation or the five-pattern raw + transition shape from Rebar. + +Perfloop optimized the board it was given. Rebar exposed the omitted shapes. +The arena now has three focused rows: + +- `multi/multi_N1_unicode_pair_miss_1_5mb` +- `multi/multi_N5_raw_transition_miss_5mb` +- `multi/multi_N5_raw_transition_late_hit_5mb` + +Those rows bring the board to 36. All 36 remain below 1.0 `x_vs_best` on both +hosts after the Rebar work. + +## The benchmark contracts + +| | casei arena | Rebar audit | +|---|---|---| +| answer | first byte offset, leftmost match, or overlap-allowed single-needle count | count or total span of every non-overlapping match | +| compilation | included in `IndexFold`; outside repeated `Matcher` searches | matcher compiled before timing, like the other Rebar engines | +| pattern sets | one and many | one and finite alternations | +| folding | Unicode simple folding on every row | Unicode on 5 rows, ASCII-only on 13 | +| timing | in-process paired windows, alternating order, three complete passes | Rebar runner protocol, three passes, pinned to one core | + +The audit adapter validates complete enumeration against an independent +simple-fold source scan before warmup. The timed iteration calls `Matcher.Each` +with only a count or span sink. + +## All 18 rows + +`casei / best` is the median of three per-pass ratios. The named competitor is +the fastest by its three-pass median. Bold values are wins. + +| Rebar row | requested folding | Ice Lake | Sapphire Rapids | +|---|---|---:|---:| +| `curated/01-literal/sherlock-casei-en` | ASCII-only* | 4.48× (Hyperscan) | 4.93× (Hyperscan) | +| `curated/01-literal/sherlock-casei-ru` | Unicode | **0.87×** (PCRE2-JIT) | **0.90×** (PCRE2-JIT) | +| `curated/02-literal-alternate/sherlock-casei-en` | ASCII-only* | 4.69× (Hyperscan) | 4.91× (Hyperscan) | +| `curated/02-literal-alternate/sherlock-casei-ru` | Unicode | **0.88×** (Hyperscan) | **0.84×** (Hyperscan) | +| `hyperscan/literal-casei-english-nosom` | ASCII-only* | 3.55× (Hyperscan) | 4.32× (Hyperscan) | +| `hyperscan/literal-casei-english-som` | ASCII-only* | 3.53× (Hyperscan) | 4.39× (Hyperscan) | +| `hyperscan/literal-casei-russian-nosom` | Unicode | **0.36×** (rust/regex) | **0.29×** (Hyperscan) | +| `hyperscan/literal-casei-russian-som` | Unicode | **0.36×** (rust/regex) | **0.29×** (Hyperscan) | +| `imported/leipzig/tom-sawyer-huckle-fin-insensitive` | ASCII-only* | 2.37× (Hyperscan) | 2.10× (Hyperscan) | +| `imported/leipzig/twain-insensitive` | ASCII-only* | 1.11× (Hyperscan) | 1.08× (Hyperscan) | +| `imported/sherlock/name-alt3-casei` | ASCII-only* | **0.70×** (rust/regex) | **0.63×** (rust/regex) | +| `imported/sherlock/name-alt5-casei` | ASCII-only* | **0.89×** (rust/regex) | **0.85×** (rust/regex) | +| `imported/sherlock/name-holmes-casei` | ASCII-only* | **0.57×** (PCRE2-JIT) | **0.55×** (PCRE2-JIT) | +| `imported/sherlock/name-sherlock-casei` | ASCII-only* | 1.54× (PCRE2-JIT) | 1.84× (PCRE2-JIT) | +| `imported/sherlock/name-sherlock-holmes-casei` | ASCII-only* | 2.50× (PCRE2-JIT) | 3.01× (PCRE2-JIT) | +| `imported/sherlock/the-casei` | ASCII-only* | **0.78×** (PCRE2-JIT) | **0.66×** (PCRE2-JIT) | +| `opt/prefilter/literal-casei-english` | ASCII-only* | 1.90× (PCRE2-JIT) | 2.34× (PCRE2-JIT) | +| `opt/prefilter/literal-casei-russian` | Unicode | **0.64×** (PCRE2-JIT) | **0.67×** (PCRE2-JIT) | + +`*` Rebar disables Unicode-aware folding. `casei` would match Unicode fold +mates that these definitions exclude. The recorded corpora happen to produce +the expected outputs, so their timings are useful stress data. Their semantic +contract stays outside the 5/5 result. ## Correctness and inventory closure -Every recorded runner invocation returned rebar's expected result on each of -the 18 performance workloads it entered. On both hosts, `casei` also passed the -two compatible behavior checks. The incompatible behavior row is: +Every recorded invocation returned Rebar's expected answer on the 18 +performance workloads. `casei` also passed the two compatible behavior checks. +The third behavior check is intentionally incompatible: ```text -test/unicode/case/ascii-only: pattern "s", haystack "ſ" -rebar with unicode=false: 0 matches -casei Unicode simple fold: 1 match +test/unicode/case/ascii-only +pattern: "s" +haystack: "ſ" +Rebar with unicode=false: 0 matches +casei simple folding: 1 match ``` -The audit also inspected the remaining case-insensitive rebar definitions: - -- `curated/03-date/*` and `wild/url/*` are general regex grammars. -- `curated/13-noseyparker/*` loads a large rule file whose caseless rules also - use classes, boundaries, captures, and bounded repetition; its search and - compile workloads are general-regex workloads, not finite literal sets. -- `imported/sherlock/name-alt4-casei` contains a character class and `+`. -- `wild/ruff`, `reported/p893-hir-case-folding`, and - `reported/i988-cloudflare-compile` exercise inline flags, classes, - repetition, captures, or compile time. - -Those are outside a literal/finite-alternation API. Every caseless rebar row -that can be represented as one literal or a finite set of literals is accounted -for above. +The remaining case-insensitive Rebar definitions use general regex features: +classes, captures, repetition, boundaries, inline flags, or compile-time rule +sets. They cannot be represented by a literal or finite literal-set API. The +18 rows above account for every caseless Rebar workload that can. ## Measurement record -The exact adapter, pinned integration script, six raw CSVs, and an independent -ratio calculator are checked in under -[`audit/rebar/`](audit/rebar/README.md). Running -`python3 audit/rebar/summarize.py` reproduces this page's table and summaries -from those receipts. - | item | recorded value | |---|---| -| casei source | tree `d1f73802d35c29009a433eaaf9c2b51113ab5c95`, merged as [`3954dbe`](https://github.com/tsenart/casei/commit/3954dbe40e8e21c4c7b2e2716f22647dd7cd880c) | -| rebar source | `463d00f31887e84c38467805b9e3122c314b9521` | +| Rebar source | `463d00f31887e84c38467805b9e3122c314b9521` | | selected field | Hyperscan 5.4.2, PCRE2 10.47 JIT, rust/regex 1.12.4 | | hosts | GenuineIntel family 6/model 106 Ice Lake and family 6/model 143 Sapphire Rapids, both with AVX-512F/BW/VBMI | -| passes | three per host, with up to 100 warmups/200 ms and 1,000 measured iterations/500 ms per benchmark | -| plan setup | outside rebar's timed iteration, matching the other engines | -| entrants | three or four per row including `casei`, as selected by each upstream definition | - -The selected field contains the three leaders in rebar's published records for -these literal rows. A displayed win is scoped to that leader set. Any unmeasured -entrant could only make the ratio worse. - -One upstream build detail is recorded for reproducibility: rebar's vendored -PCRE2 10.47 snapshot contains `pcre2posix.c` but not its unused -`pcre2posix.h`. The audit omitted that POSIX wrapper from the build; rebar's -runner uses the native PCRE2 API, so no compiled search or JIT code changed. - -## Public work on the losses - -The first four Perfloop experiments are public and stopped: - -- [Compile shared interior UTF-8 anchors for multi-pattern plans](https://app.perfloop.ai/t/oss/case_jws72csfa9) - explored the roughly 9x multi-pattern loss. -- [Compile dispersed width-stable Unicode byte probes](https://app.perfloop.ai/t/oss/case_b2m0dmh5wa) - explored the two single-pattern losses. -- [Compile width-stable Unicode byte confirmations](https://app.perfloop.ai/t/oss/case_tgkp9bs0r6) - explored compiled raw-byte confirmation. -- [Carry the confirmed end into repeated matching](https://app.perfloop.ai/t/oss/case_1jg4we7k3s) - tested the narrower repeated-call explanation. The one-pass control and - repeated `Find` remained effectively tied on the worst row. - -Two later Cases carry the surviving work: - -- [Keep N=1 confirmation inside the AVX-512 scan](https://app.perfloop.ai/t/oss/case_s8c41a1per) - is verified on one targeted false-survivor row. It moved - `x_vs_best` from `4.547` to `0.7328` over ten randomized pairs. - [PR #10](https://github.com/tsenart/casei/pull/10) remains open because that - result has not been reproduced across the complete board on both hosts. -- [Replace the decoded transition loop with one raw-byte plan](https://app.perfloop.ai/t/oss/case_rmg4fdm3me) - is open. It targets the shared cost that remains after filtering: decoding a - surviving position, mapping it into the fold-token alphabet, and then - advancing the exact plan. - -Any change accepted into `casei` must beat all five Unicode-equivalent Rebar -rows on Ice Lake and Sapphire Rapids, preserve the one-engine design and full -correctness contract, and keep every current `BenchmarkBar` row below 1.0 -`x_vs_best`. - -## Required next work - -The next construction must: - -1. compile once and keep one package-owned plan; -2. combine selective interior anchors from several patterns into one shared - byte-level filter; -3. replace hot-path rune-to-token map lookups with compiled raw-byte - transitions where the plan permits it; -4. preserve exact non-overlapping enumeration through the same state machine; - and -5. beat the fastest eligible entrant on all five Unicode-equivalent rows before - any count-all performance claim is made. - -The public performance claim therefore covers the 33-row arena contract. It -does not claim leadership for non-overlapping enumeration. +| passes | three per host | +| warmup bound | 100 iterations or 200 ms | +| measurement bound | 1,000 iterations or 500 ms | +| CPU placement | runner and child engines pinned to core 2 | +| plan setup | outside the timed iteration | + +The adapter, pinned integration script, six raw CSVs, receipt hashes, and ratio +calculator are checked in under [`audit/rebar/`](audit/rebar/README.md). + +```sh +(cd audit/rebar/results && sha256sum -c SHA256SUMS) +python3 audit/rebar/summarize.py +``` + +One upstream build detail is preserved in the reproducer. Rebar's vendored +PCRE2 snapshot contains `pcre2posix.c` without its unused header. The audit +omits that POSIX wrapper. Rebar uses the native PCRE2 API, so its JIT search +code is unchanged. + +## Experiment history + +The gaps were explored in public Perfloop Cases: + +- [Shared interior UTF-8 anchors](https://app.perfloop.ai/t/oss/case_jws72csfa9) +- [Dispersed width-stable probes](https://app.perfloop.ai/t/oss/case_b2m0dmh5wa) +- [Raw byte confirmation](https://app.perfloop.ai/t/oss/case_tgkp9bs0r6) +- [Carry confirmed ends into repeated matching](https://app.perfloop.ai/t/oss/case_1jg4we7k3s) + +The last case rejected the idea that API restart cost was the main problem. +The selective filter and native confirmation work survived. The current result +combines those pieces with the exact origin gate and wider assembly schedules. diff --git a/arena/bar_test.go b/arena/bar_test.go index 537750a..db15991 100644 --- a/arena/bar_test.go +++ b/arena/bar_test.go @@ -8,6 +8,7 @@ package arena_test import ( "fmt" + "sort" "testing" "time" @@ -21,26 +22,40 @@ import ( vectorscan "github.com/tsenart/casei/arena/vectorscan" ) -// timeOp returns ns/op for one operation. It times manually rather than -// through testing.Benchmark, which cannot be nested inside a running -// benchmark, and takes the best of three samples to reduce sensitivity to -// transient host load. -func timeOp(op func()) float64 { +// timeWindow returns ns/op for one manually timed window. testing.Benchmark +// cannot be nested inside a running benchmark. +func timeWindow(op func()) float64 { const budget = 25 * time.Millisecond - best := 0.0 - for sample := 0; sample < 3; sample++ { - n := 0 - start := time.Now() - for time.Since(start) < budget { - op() - n++ - } - ns := float64(time.Since(start).Nanoseconds()) / float64(n) - if best == 0 || ns < best { - best = ns + n := 0 + start := time.Now() + for time.Since(start) < budget { + op() + n++ + } + return float64(time.Since(start).Nanoseconds()) / float64(n) +} + +// pairedRatio measures the candidate beside one competitor six times, with +// each operation going first in three pairs. The median paired ratio reduces +// drift from CPU migration, frequency changes, and host load between timing +// windows. +func pairedRatio(candidate, competitor func()) float64 { + candidate() + competitor() + var ratios [6]float64 + for round := range ratios { + var candidateNS, competitorNS float64 + if round%2 == 0 { + candidateNS = timeWindow(candidate) + competitorNS = timeWindow(competitor) + } else { + competitorNS = timeWindow(competitor) + candidateNS = timeWindow(candidate) } + ratios[round] = candidateNS / competitorNS } - return best + sort.Float64s(ratios[:]) + return (ratios[2] + ratios[3]) / 2 } // velozVectorBits is deliberately strict: Veloz has an SSE/scalar fallback, @@ -132,45 +147,44 @@ func BenchmarkBar(b *testing.B) { for _, s := range scenarios { s := s b.Run("single/"+s.name, func(b *testing.B) { - cand := timeOp(func() { sink = runSingleScenario(casei.IndexFold, s) }) - - best := timeOp(func() { sink = runSingleScenario(indexRegexp, s) }) + candidate := func() { sink = runSingleScenario(casei.IndexFold, s) } + best := pairedRatio(candidate, func() { sink = runSingleScenario(indexRegexp, s) }) competitors := 1 - if v := timeOp(func() { sink = runSingleScenario(indexPCRE2, s) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { sink = runSingleScenario(indexPCRE2, s) }); ratio > best { + best = ratio } competitors++ rure := rureSingles[s.needle] - rureTime := timeOp(func() { sink = runSingleScenario(indexRure, s) }) + rureRatio := pairedRatio(candidate, func() { sink = runSingleScenario(indexRure, s) }) // The Rust adapter records the backend reached by this exact query. // A query that did not reach memchr AVX2 is diagnostic only; it must // not race a target-width field entrant under a CPU-flag label. if rure.VectorBits() == 256 { - if rureTime < best { - best = rureTime + if rureRatio > best { + best = rureRatio } competitors++ } - if v := timeOp(func() { sink = runSingleScenario(indexVectorscan, s) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { sink = runSingleScenario(indexVectorscan, s) }); ratio > best { + best = ratio } competitors++ if stringZillaAvailable { - if v := timeOp(func() { sink = runSingleScenario(indexStringZilla, s) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { sink = runSingleScenario(indexStringZilla, s) }); ratio > best { + best = ratio } competitors++ } if !s.utf8 && velozVectorBits() == 256 { - if v := timeOp(func() { sink = runSingleScenario(veloz.IndexFold, s) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { sink = runSingleScenario(veloz.IndexFold, s) }); ratio > best { + best = ratio } competitors++ } for b.Loop() { - sink = runSingleScenario(casei.IndexFold, s) + candidate() } - b.ReportMetric(cand/best, "x_vs_best") + b.ReportMetric(best, "x_vs_best") b.ReportMetric(float64(competitors), "competitors") b.ReportMetric(float64(competitors+1), "entrants") reportSingleDispatch(b, s) @@ -182,58 +196,58 @@ func BenchmarkBar(b *testing.B) { scenarioIndex := scenarioIndex b.Run("multi/"+s.name, func(b *testing.B) { m := casei.NewMatcher(s.patterns) - cand := timeOp(func() { _, matcherFound = m.Find(s.haystack) }) + candidate := func() { _, matcherFound = m.Find(s.haystack) } re := regexpAltFor(s.patterns) - best := timeOp(func() { matcherSink = len(re.FindStringIndex(s.haystack)) }) + best := pairedRatio(candidate, func() { matcherSink = len(re.FindStringIndex(s.haystack)) }) competitors := 1 pcre := pcre2Alts[scenarioIndex] - if v := timeOp(func() { _, _, matcherFound = pcre.Find(s.haystack) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { _, _, matcherFound = pcre.Find(s.haystack) }); ratio > best { + best = ratio } competitors++ rure := rureAlts[scenarioIndex] - rureTime := timeOp(func() { _, _, matcherFound = rure.Find(s.haystack) }) + rureRatio := pairedRatio(candidate, func() { _, _, matcherFound = rure.Find(s.haystack) }) if rure.VectorBits() == 256 { - if rureTime < best { - best = rureTime + if rureRatio > best { + best = rureRatio } competitors++ } vscan := vectorscanAlts[scenarioIndex] - if v := timeOp(func() { _, _, matcherFound = vscan.Find(s.haystack) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { _, _, matcherFound = vscan.Find(s.haystack) }); ratio > best { + best = ratio } competitors++ if stringZillaAvailable { stringzilla := stringZillaAlts[scenarioIndex] - if v := timeOp(func() { _, _, matcherFound = stringzilla.Find(s.haystack) }); v < best { - best = v + if ratio := pairedRatio(candidate, func() { _, _, matcherFound = stringzilla.Find(s.haystack) }); ratio > best { + best = ratio } competitors++ } supplemental := 0 rust := rustACAlts[scenarioIndex] if !s.utf8 { - rustTime := timeOp(func() { _, _, matcherFound = rust.Find(s.haystack) }) + rustRatio := pairedRatio(candidate, func() { _, _, matcherFound = rust.Find(s.haystack) }) // The direct Rust DFA exposes the memchr backend reached by this // exact prefilter query. Do not call an unobserved scalar/SSE path // an AVX2 field entrant merely because this process has AVX2. if rust.VectorBits() == 256 { - if rustTime < best { - best = rustTime + if rustRatio > best { + best = rustRatio } competitors++ } goAC := acBuild(s.patterns, true) - _ = timeOp(func() { _, matcherFound = acFirst(&goAC, s.haystack) }) + _ = pairedRatio(candidate, func() { _, matcherFound = acFirst(&goAC, s.haystack) }) supplemental++ } for b.Loop() { - _, matcherFound = m.Find(s.haystack) + candidate() } - b.ReportMetric(cand/best, "x_vs_best") + b.ReportMetric(best, "x_vs_best") b.ReportMetric(float64(competitors), "competitors") b.ReportMetric(float64(competitors+1+supplemental), "entrants") reportMultiDispatch(b, s, m.VectorBits(), rure, rust, vscan) diff --git a/arena/matcher_bench_test.go b/arena/matcher_bench_test.go index 9c36ca3..abcc9f8 100644 --- a/arena/matcher_bench_test.go +++ b/arena/matcher_bench_test.go @@ -52,6 +52,56 @@ func genNeedles(n int, format string) []string { return out } +// unicodePairConfirmMissCorpus repeats a near-full-width false match at the +// pair-pair anchor density measured on the Russian corpus. It exercises the +// N=1 Matcher path without giving any engine a true-match early exit. +func unicodePairConfirmMissCorpus() string { + const needle = "приключения лилий" + const haystackBytes = 1_570_556 + const survivors = 2_134 + + falseLiteral := needle[:len(needle)-len("й")] + "я" + bytes := []byte(strings.Repeat("x", haystackBytes)) + step := len(bytes) / survivors + inserted := 0 + for at := 0; at+len(falseLiteral) <= len(bytes) && inserted < survivors; at += step { + copy(bytes[at:], falseLiteral) + inserted++ + } + if inserted != survivors { + panic(fmt.Sprintf("inserted %d false survivors, want %d", inserted, survivors)) + } + return string(bytes) +} + +// rawTransitionPatterns are ordinary Unicode simple-fold literals with distinct +// Cyrillic roots. The companion rows keep an admitted root followed by an ASCII +// mismatch at a fixed density, and add one late full literal for the hit case. +// They exercise a shared multi-pattern plan against every native field entrant; +// no production path observes these fixture names or values. +var rawTransitionPatterns = []string{ + "Шерлок Холмс", + "Джон Уотсон", + "Ирен Адлер", + "инспектор Лестрейд", + "профессор Мориарти", +} + +func rawTransitionCorpus(bytes int, lateMatch bool) string { + const period = 256 + if bytes < period { + panic("raw transition corpus is shorter than its period") + } + out := []byte(strings.Repeat("x", ((bytes+period-1)/period)*period)) + for at := 0; at+len("Дx") <= len(out); at += period { + copy(out[at:], "Дx") + } + if lateMatch { + copy(out[len(out)-period:], rawTransitionPatterns[0]) + } + return string(out) +} + var multiScenarios = func() []multiScenario { logs1m := buildLogCorpus(1 << 20) prose1m := buildProseCorpus(1 << 20) @@ -79,6 +129,9 @@ var multiScenarios = func() []multiScenario { // about the tier this repository exists for. {"multi_N512_miss_hazard_64kb", cyr1m[:64<<10], genHazardNeedles(512), true}, {"multi_N8_hit_log_1mb", plant(logs1m, "Payment Declined", 4), hit8, false}, + {"multi_N1_unicode_pair_miss_1_5mb", unicodePairConfirmMissCorpus(), []string{"приключения лилий"}, true}, + {"multi_N5_raw_transition_miss_5mb", rawTransitionCorpus(5<<20, false), rawTransitionPatterns, true}, + {"multi_N5_raw_transition_late_hit_5mb", rawTransitionCorpus(5<<20, true), rawTransitionPatterns, true}, {"multi_N8_miss_ru_1mb", cyr1m, genNeedles(8, "щупальце%d"), true}, {"multi_N64_miss_ru_64kb", cyr1m[:64<<10], genNeedles(64, "щупальце%d"), true}, // This is the all-ASCII half of the mixed-fold hazard set. It keeps the diff --git a/ascii_partition_test.go b/ascii_partition_test.go new file mode 100644 index 0000000..f243b0c --- /dev/null +++ b/ascii_partition_test.go @@ -0,0 +1,352 @@ +package casei + +import ( + "math/rand/v2" + "strings" + "testing" +) + +// asciiPartitionPatterns deliberately leave the root filter too broad while +// retaining a complete, bounded ASCII triple projection. Nine ASCII literals +// disable the eight-entry pair projection; the Cyrillic roots make the regular +// mixed-byte filter unusable. This is the shape where one high byte otherwise +// poisons the remainder of an otherwise block-friendly scan. +func asciiPartitionPatterns() []string { + return []string{ + "abc0", "abc1", "def0", "def1", "ghi0", "ghi1", "jkl0", "jkl1", "mno0", + "абв0", "где1", "жзи2", "йкл3", "мно4", "прс5", "туф6", "хцч7", "шщъ8", "ыьэ9", + } +} + +func decodedPlanFind(p *searchPlan, haystack string) (Match, bool) { + var inlineStarts [256]int + starts := inlineStarts[:] + if p.maxUnits > len(starts) { + starts = make([]int, p.maxUnits) + } + return p.findUnfilteredWithStarts(haystack, starts) +} + +func TestASCIIPartitionPlanAdmission(t *testing.T) { + plan := newSearchPlan(asciiPartitionPatterns()) + if runtimeVectorBits() != 512 { + t.Skipf("ASCII partition is runtime-gated to AVX-512; vector width %d", runtimeVectorBits()) + } + if !plan.asciiPartitionUsable() { + t.Fatalf("plan did not retain the partition route: triples=%d complete=%t shufti=%t pair=%t filter=%t", + plan.asciiTriples.n, plan.asciiTriplesComplete, plan.asciiTriples.shufti.usable(), + plan.asciiPairAnchors.usable(), plan.filter.usable()) + } + if plan.maxBytes == 0 || plan.maxBytes < plan.maxUnits { + t.Fatalf("maximum source width = %d for %d units", plan.maxBytes, plan.maxUnits) + } + if plan.filter.usable() || plan.asciiPairAnchors.usable() || plan.rawByteMulti.usable() { + t.Fatalf("fixture entered a route outside the intended gap: filter=%t pair=%t raw=%t", plan.filter.usable(), plan.asciiPairAnchors.usable(), plan.rawByteMulti.usable()) + } +} + +func TestASCIIPartitionDifferential(t *testing.T) { + patterns := asciiPartitionPatterns() + plan := newSearchPlan(patterns) + matcher := NewMatcher(patterns) + rng := rand.New(rand.NewPCG(20260829, 17)) + units := []string{ + "x", " ", "a", "A", "b", "c", "0", "Д", "д", "Ж", "ж", "€", "ᲁ", + "\x00", "\xff", "\x80", "\xc2\x80", "\xe2\x84\xaa", + } + for iteration := 0; iteration < 2000; iteration++ { + var input strings.Builder + for range 1 + rng.IntN(160) { + input.WriteString(units[rng.IntN(len(units))]) + } + if iteration%3 == 0 { + input.WriteString(patterns[rng.IntN(len(patterns))]) + } + haystack := input.String() + want, wantOK := decodedPlanFind(plan, haystack) + got, gotOK := matcher.Find(haystack) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("iteration %d Find(%x) = %+v,%t; decoded = %+v,%t", iteration, haystack, got, gotOK, want, wantOK) + } + ref, refOK := refFind(haystack, patterns) + if gotOK != refOK || gotOK && got != ref { + t.Fatalf("iteration %d Find(%x) = %+v,%t; reference = %+v,%t", iteration, haystack, got, gotOK, ref, refOK) + } + } +} + +func TestASCIIPartitionPositionDensityAndBoundaries(t *testing.T) { + patterns := asciiPartitionPatterns() + plan := newSearchPlan(patterns) + matcher := NewMatcher(patterns) + for _, size := range []int{1, 63, 64, 127, 1024, 8192} { + for _, gap := range []int{1, 7, 31, 127, 511} { + var input strings.Builder + for at := 0; at < size; at += gap { + input.WriteString(strings.Repeat("x", min(gap, size-at))) + input.WriteString("€") + } + haystack := input.String() + want, wantOK := refFind(haystack, patterns) + if got, gotOK := matcher.Find(haystack); gotOK != wantOK || gotOK && got != want { + t.Fatalf("size %d gap %d Find = %+v,%t; want %+v,%t", size, gap, got, gotOK, want, wantOK) + } + } + } + + highAt := 64 + spanEnd := highAt + len("€") + boundaryStart := spanEnd + plan.maxBytes - 1 + boundary := []byte(strings.Repeat("x", boundaryStart+len("abc0")+32)) + copy(boundary[highAt:], "€") + copy(boundary[boundaryStart:], "abc0") + secondHighAt := 128 + interWindowStart := secondHighAt - plan.maxBytes - 1 + interWindow := []byte(strings.Repeat("x", 256)) + copy(interWindow[highAt:], "€") + copy(interWindow[secondHighAt:], "€") + copy(interWindow[interWindowStart:], "abc0") + + for _, haystack := range []string{ + "abc0" + "€" + strings.Repeat("x", 64), + strings.Repeat("x", 64) + "€" + "abc0", + strings.Repeat("x", 64) + "ᲁ" + "abc0", + strings.Repeat("x", 64) + "\xff" + "abc0", + strings.Repeat("x", 64) + "\x80" + "abc0", + strings.Repeat("x", 64) + "\xc2\x80" + "abc0", + strings.Repeat("x", 64) + "\x00" + "abc0", + strings.Repeat("x", 64) + "abc0" + "€" + "def1", + strings.Repeat("x", 64) + "€" + strings.Repeat("x", 64) + "\xff" + "ghi2", + strings.Repeat("x", 76) + "jkl0" + strings.Repeat("x", 5) + "\xff" + strings.Repeat("x", 512), + string(boundary), + string(interWindow), + } { + want, wantOK := refFind(haystack, patterns) + if got, gotOK := matcher.Find(haystack); gotOK != wantOK || gotOK && got != want { + t.Fatalf("boundary Find(%x) = %+v,%t; want %+v,%t", haystack, got, gotOK, want, wantOK) + } + } +} + +func TestASCIIPartitionWidthChangingBoundaries(t *testing.T) { + patterns := append(asciiPartitionPatterns(), "абвkK0", "гдеsſ1") + plan := newSearchPlan(patterns) + if !plan.asciiPartitionUsable() { + t.Skipf("width-changing fixture is not admitted on vector width %d", runtimeVectorBits()) + } + if plan.maxBytes <= plan.maxUnits { + t.Fatalf("width-changing fixture did not widen windows: maxBytes=%d maxUnits=%d", plan.maxBytes, plan.maxUnits) + } + matcher := NewMatcher(patterns) + for _, haystack := range []string{ + strings.Repeat("x", 73) + "абвKK0" + strings.Repeat("x", 73), + strings.Repeat("x", 73) + "гдеSſ1" + strings.Repeat("x", 73), + strings.Repeat("x", 73) + "абвkK0" + "€" + "гдеsſ1", + } { + want, wantOK := refFind(haystack, patterns) + if got, gotOK := matcher.Find(haystack); gotOK != wantOK || gotOK && got != want { + t.Fatalf("width-changing Find(%x) = %+v,%t; want %+v,%t; maxBytes=%d", haystack, got, gotOK, want, wantOK, plan.maxBytes) + } + } +} + +func TestASCIIPartitionEachContract(t *testing.T) { + patterns := append(asciiPartitionPatterns(), "abc0") + matcher := NewMatcher(patterns) + for _, haystack := range []string{ + "abc0xx€ABC1xxdef0", + strings.Repeat("x", 91) + "€" + "ghi1" + strings.Repeat("x", 73) + "\xff" + "jkl0", + strings.Repeat("x", 512) + "ᲁ" + "mno0" + strings.Repeat("x", 512) + "abc1", + } { + want := refEach(haystack, patterns) + var got []refEachResult + if complete := matcher.Each(haystack, func(match Match, width int) bool { + got = append(got, refEachResult{match: match, width: width}) + return true + }); !complete { + t.Fatalf("Each(%x) stopped early", haystack) + } + if len(got) != len(want) { + t.Fatalf("Each(%x) returned %d matches, want %d: got=%+v want=%+v", haystack, len(got), len(want), got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("Each(%x) match %d = %+v, want %+v", haystack, i, got[i], want[i]) + } + } + } +} + +func TestASCIIPartitionReportsWorkSplit(t *testing.T) { + patterns := asciiPartitionPatterns() + plan := newSearchPlan(patterns) + if !plan.asciiPartitionUsable() { + t.Skipf("ASCII partition is runtime-gated to AVX-512; vector width %d", runtimeVectorBits()) + } + var input strings.Builder + for input.Len()+512+len("€") <= 1<<16 { + input.WriteString(strings.Repeat("x", 512)) + input.WriteString("€") + } + input.WriteString(strings.Repeat("x", 1<<16-input.Len())) + haystack := input.String() + var stats asciiPartitionStats + if _, ok := plan.findUnfilteredWithStats(haystack, &stats); ok { + t.Fatal("setup unexpectedly matched") + } + if stats.fallbackEntries != 0 || stats.decodedWindows == 0 || stats.decodedWindowBytes == 0 { + t.Fatalf("partition diagnostics = %+v", stats) + } + if stats.highBytes == 0 || stats.firstExceptional <= 0 || stats.asciiCandidateBytes <= stats.decodedWindowBytes { + t.Fatalf("partition did not expose sparse ASCII work: %+v", stats) + } + + fallbackHaystack := strings.Repeat("x", 256) + "€" + stats = asciiPartitionStats{} + if _, ok := plan.findUnfilteredWithStats(fallbackHaystack, &stats); ok { + t.Fatal("fallback setup unexpectedly matched") + } + if stats.fallbackEntries != 1 || stats.firstExceptional < 0 || stats.decodedWindows != 0 { + t.Fatalf("tail fallback diagnostics = %+v", stats) + } +} + +func TestASCIIPartitionRejectsDenseExceptionalInput(t *testing.T) { + if runtimeVectorBits() != 512 { + t.Skipf("ASCII partition is runtime-gated to AVX-512; vector width %d", runtimeVectorBits()) + } + plan := newSearchPlan(asciiPartitionPatterns()) + for _, tc := range []struct { + name string + interval int + value byte + }{ + {name: "high", interval: 32, value: 0xe2}, + {name: "nul", interval: 128, value: 0}, + } { + input := []byte(strings.Repeat("x", 1<<20)) + for at := 0; at < len(input); at += tc.interval { + input[at] = tc.value + } + var stats asciiPartitionStats + if _, ok := plan.findUnfilteredWithStats(string(input), &stats); ok { + t.Fatalf("%s setup unexpectedly matched", tc.name) + } + if stats.fallbackEntries != 1 || stats.decodedWindows != 0 { + t.Fatalf("%s dense input was partitioned: %+v", tc.name, stats) + } + } + + lateDense := []byte(strings.Repeat("x", 1<<20)) + copy(lateDense[0:3], "€") + for at := 4096; at < len(lateDense)-2; at += 32 { + copy(lateDense[at:at+3], "€") + } + var stats asciiPartitionStats + if _, ok := plan.findUnfilteredWithStats(string(lateDense), &stats); ok { + t.Fatal("late dense setup unexpectedly matched") + } + if stats.fallbackEntries != 1 { + t.Fatalf("late dense input was not rejected while discovering spans: %+v", stats) + } + + contiguous := []byte(strings.Repeat("x", 1<<20)) + copy(contiguous[0:3], "€") + copy(contiguous[4096:], strings.Repeat("€", 1<<16)) + stats = asciiPartitionStats{} + if _, ok := plan.findUnfilteredWithStats(string(contiguous), &stats); ok { + t.Fatal("contiguous dense setup unexpectedly matched") + } + if stats.fallbackEntries != 1 { + t.Fatalf("contiguous dense input was not rejected early: %+v", stats) + } + + // A sparse first span must not make the partitioner spend a decoded window + // before it discovers a later contiguous valid-UTF-8 region is dense. + sparsePrefixDenseSuffix := []byte(strings.Repeat("x", 1<<20)) + copy(sparsePrefixDenseSuffix[64:], "€") + copy(sparsePrefixDenseSuffix[4096:], strings.Repeat("€", 1<<16)) + stats = asciiPartitionStats{} + if _, ok := plan.findUnfilteredWithStats(string(sparsePrefixDenseSuffix), &stats); ok { + t.Fatal("sparse-prefix setup unexpectedly matched") + } + if stats.fallbackEntries != 1 || stats.decodedWindows != 0 { + t.Fatalf("sparse-prefix dense input was partitioned before fallback: %+v", stats) + } + + sampledDenseRegion := []byte(strings.Repeat("x", 1<<20)) + copy(sampledDenseRegion[64:], "€") + for at := 200000; at+3 < 700000; at += 8 { + copy(sampledDenseRegion[at:], "€") + } + if asciiPartitionSparseEnough(string(sampledDenseRegion), 64) { + t.Fatal("sampled dense region passed admission") + } + stats = asciiPartitionStats{} + if _, ok := plan.findUnfilteredWithStats(string(sampledDenseRegion), &stats); ok { + t.Fatal("sampled dense setup unexpectedly matched") + } + if stats.fallbackEntries != 1 || stats.decodedWindows != 0 { + t.Fatalf("sampled dense input was admitted before fallback: %+v", stats) + } + + widePatterns := asciiPartitionPatterns() + widePatterns[0] = strings.Repeat("q", 100000) + "0" + widePlan := newSearchPlan(widePatterns) + if !widePlan.asciiPartitionUsable() || widePlan.maxBytes < 100000 { + t.Fatalf("wide pattern did not retain the partition shape: usable=%t maxBytes=%d", widePlan.asciiPartitionUsable(), widePlan.maxBytes) + } + for _, tc := range []struct { + length int + highAt int + }{{length: 256, highAt: 189}, {length: 131072, highAt: 64}} { + wideHaystack := []byte(strings.Repeat("x", tc.length)) + copy(wideHaystack[tc.highAt:], "€") + stats = asciiPartitionStats{} + if _, ok := widePlan.findUnfilteredWithStats(string(wideHaystack), &stats); ok { + t.Fatalf("wide-pattern setup unexpectedly matched at length %d", tc.length) + } + if stats.fallbackEntries != 1 || stats.decodedWindows != 0 { + t.Fatalf("wide pattern admitted a whole-input decoded window at length %d: %+v", tc.length, stats) + } + } + + lateMalformed := []byte(strings.Repeat("x", 1<<16)) + copy(lateMalformed[0:3], "€") + lateMalformed[4096] = 0xff + copy(lateMalformed[4100:], "jkl0") + matcher := NewMatcher(asciiPartitionPatterns()) + want, wantOK := refFind(string(lateMalformed), asciiPartitionPatterns()) + if got, gotOK := matcher.Find(string(lateMalformed)); gotOK != wantOK || gotOK && got != want { + t.Fatalf("late malformed Find = %+v,%t; want %+v,%t", got, gotOK, want, wantOK) + } + +} + +func TestASCIIPartitionKeepsCrossSpanMatchLeftmost(t *testing.T) { + patterns := append(asciiPartitionPatterns(), "abcdefgh€", "defg") + matcher := NewMatcher(patterns) + haystack := strings.Repeat("x", 70) + "abcdefgh€" + strings.Repeat("x", 512) + want := Match{Pattern: len(asciiPartitionPatterns()), Start: 70} + if got, ok := matcher.Find(haystack); !ok || got != want { + t.Fatalf("cross-span Find = %+v,%t; want %+v,true", got, ok, want) + } +} + +func TestASCIIPartitionFindAllocatesNothing(t *testing.T) { + matcher := NewMatcher(asciiPartitionPatterns()) + haystack := strings.Repeat("x", 64) + "€" + strings.Repeat("x", 64<<10) + if got, ok := matcher.Find(haystack); ok { + t.Fatalf("setup Find = %+v,%t", got, ok) + } + if allocs := testing.AllocsPerRun(100, func() { _, _ = matcher.Find(haystack) }); allocs != 0 { + t.Fatalf("partitioned Find allocations = %g, want 0", allocs) + } +} + +func TestASCIIPartitionRejectsOpaqueContinuationPlans(t *testing.T) { + plan := newSearchPlan([]string{"\x80abc", "def0", "абв1", "где2", "жзи3", "йкл4", "мно5", "прс6", "туф7", "хцч8"}) + if plan.asciiPartitionUsable() { + t.Fatal("opaque continuation plan entered the ASCII partition route") + } +} diff --git a/audit/acceptance/README.md b/audit/acceptance/README.md new file mode 100644 index 0000000..0484643 --- /dev/null +++ b/audit/acceptance/README.md @@ -0,0 +1,82 @@ +# Current two-host acceptance record + +This directory holds the raw `BenchmarkBar` transcripts used by the current +README claim. + +| host | rows | worst median | worst sample | median speedup | entrants | +|---|---:|---:|---:|---:|---:| +| Ice Lake, family 6/model 106 | 36/36 | 0.9624 | 0.9736 | 1.80× | 5-7 | +| Sapphire Rapids, family 6/model 143 | 36/36 | 0.9716 | 0.9799 | 1.56× | 5-7 | + +Every row has three samples. Every sample has `x_vs_best < 1`. `casei` reports +512-bit dispatch, Vectorscan reports a 512-bit VBMI database, and the verifier +checks every other active entrant against its declared width. + +## Verify the receipts + +```sh +(cd audit/acceptance && sha256sum -c SHA256SUMS) +sha256sum -c audit/acceptance/SOURCE_SHA256SUMS +python3 audit/acceptance/summarize.py +python3 scripts/verify_benchmarkbar.py \ + audit/acceptance/results/ice/benchmarkbar.txt +python3 scripts/verify_benchmarkbar.py \ + audit/acceptance/results/spr/benchmarkbar.txt +``` + +The verifier requires the exact 36-row inventory, three samples per row, +at least two entrants, all dispatch metrics, and every `x_vs_best` below 1.0. + +[`ablations/`](ablations/README.md) removes the origin gate, variable raw +confirmation, and returned pattern tags one at a time. Each removal breaks its +claimed field or Rebar consumer on at least one target host. + +## Measurement order + +For each row, `BenchmarkBar` pairs `casei` separately with every eligible +competitor. A pair contains six 25 ms windows. The order alternates, giving +each operation three first positions. The median paired ratio is the row's +ratio against that competitor. The largest ratio is `x_vs_best` because it +corresponds to the fastest competitor. + +The complete board was run three times with: + +```sh +taskset -c 2 go test -run '^$' -bench '^BenchmarkBar$' \ + -benchtime 30x -count 3 +``` + +Before timing, both hosts passed the full arena agreement suite against the +native field. The field was built from the pinned prepare scripts with +Vectorscan's AVX-512 VBMI target enabled. + +## Native reachability + +The three native entries added or materially changed by this result are +`literalSkipExact64`, `pairPairConfirmVBMI64`, and +`rawByteMultiAnchorSkip64`. One-shot GDB breakpoints observed all three while +their direct model tests passed on both hosts. + +```sh +go test -c -o casei.test . +gdb -q -batch -x audit/acceptance/native-reachability.gdb ./casei.test +``` + +The command file is [`native-reachability.gdb`](native-reachability.gdb). The +captured outputs are [`results/ice/gdb-native.txt`](results/ice/gdb-native.txt) +and [`results/spr/gdb-native.txt`](results/spr/gdb-native.txt). Each receipt +must contain `HIT 1`, `HIT 2`, `HIT 3`, and a final `PASS`. +[`SOURCE_SHA256SUMS`](SOURCE_SHA256SUMS) pins the source, direct tests, and GDB +command file used to build both binaries. Both hosts reported the same checksum +stream, `043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9`. + +## Why failed runs are kept + +[`methodology/`](methodology/) contains the earlier sequential-window runs. +They measured the candidate and field in distant windows and produced unstable +near-parity N=5 rows, including losing samples. Those receipts failed the +publication bar. They are retained so the change to paired timing and the +reason for it remain auditable. + +[`results/`](results/) contains the paired acceptance run. The acceptance rule +did not change: one row at or above 1.0 fails the board. diff --git a/audit/acceptance/SHA256SUMS b/audit/acceptance/SHA256SUMS new file mode 100644 index 0000000..e597a88 --- /dev/null +++ b/audit/acceptance/SHA256SUMS @@ -0,0 +1,13 @@ +205d490bb4df0a59f79529d290fd43924d949852974c4ba55d063c5af49b6603 methodology/ice/sequential-focused.txt +829ef04158a6b227efd6d93c0a9f0a85ca27653d8836cbc19111c0479dc072c7 methodology/ice/sequential-windows.txt +b4f7c8f0c67ec2a211942de875b27030125dfa1452b58932fcc2bf7da7bddbd0 methodology/spr/sequential-focused.txt +0857db9ca71e93157ef27107c880b1f2b93a6bc6ac2bad08c6073e78202ef772 methodology/spr/sequential-windows.txt +a61c8ac9eaf3f548c54ff4c92aa2ce6d24f8d11fd2d55250a27965e513a7a32c results/ice/benchmarkbar.txt +49fc55a4005c5f2fddfe47af41ddc6b256156b2c0adf5fbe385fe99e6a3c0ad6 results/ice/field-receipt.txt +11d05c54a7930a67cc1a2cefabd73ccb42bbdcfc77429fbc64f8158e9a244f94 results/spr/benchmarkbar.txt +043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9 SOURCE_SHA256SUMS +e3ad3aacb20b5e028ef3f8c8d7e9411af3dad727aef41eea50008364eab97bcc native-reachability.gdb +fd3bbb2acc7a29d33c22e63be4e630746ed0e51da768b718bbe2ab297548f9e4 results/ice/gdb-native.txt +46f49a3bd4a6f3bba2b929f285ab26f24bdcc68afd366b3fb59535a15d855166 results/spr/gdb-native.txt +b4194edb95d935bf4bf36a9371b580cdb2411ee539a80adb4051319f07f5a6ea results/spr/field-receipt.txt +753b1cf5b88cdac723b802ef76ea9cbb97771fae21e15e94d35d77b77510211f summarize.py diff --git a/audit/acceptance/SOURCE_SHA256SUMS b/audit/acceptance/SOURCE_SHA256SUMS new file mode 100644 index 0000000..3b49200 --- /dev/null +++ b/audit/acceptance/SOURCE_SHA256SUMS @@ -0,0 +1,15 @@ +e3ad3aacb20b5e028ef3f8c8d7e9411af3dad727aef41eea50008364eab97bcc audit/acceptance/native-reachability.gdb +578c9485539e8f73b2b18f28714feec690cb2b708ed58a38233160ceb861ff78 matcher.go +088e792a9e4c5290786acb6446e7ac84d3b717048bac15a77bea20d2201f0117 matcher_test.go +f270240067c73cb021848015ee09180f49c145ae11f9369b250cd668d241ebf1 plan.go +9d02d89c6929c010038ce0e417894ed874cdb22382238fe4ee14487d49742332 raw_byte.go +4139667abff6b820a536bcf2b7c811ad8504881b90170f9e286a228756fca02e raw_byte_bench_fixture_test.go +1d13cde7aef47dbaeec9eb18db41e1c4e89911285715347310e3922b54dacd3a raw_byte_multi_anchor_amd64_test.go +abc9a704dd1657394c64f729453d0a8e944d051f14a634cd35d0c17710ce4b18 raw_byte_test.go +6883b7b593e7a78354606d944541b4eb805b48ff8854180c99342671603ee951 root_amd64.go +abec0444911dbfff3b686fe42b6f654bf2a8e058644413a2738e965f05c22bbd root_amd64.s +e157e5685b8170cc9a1f5d3acf6bbc24c3a75efec54ebe70383fd98c2578720f root_amd64_test.go +2c79a1e05144319285875596d62e0b9e60ac00df1d922dabe8c204346f624337 root_other.go +5128b286c4ff45ff64256bb199cb5c2a7873af013229330a059581fb5b2f7506 root_test.go +93ae2f15e220942a972e65eeb89001856991ae71973c1ae06cb1f2784a50539f unicode_confirm.go +e57a9859047564a7c369ba3b21f39acbe908cb92b75d770b93a33a09272392f0 unicode_variable_confirm_test.go diff --git a/audit/acceptance/ablations/README.md b/audit/acceptance/ablations/README.md new file mode 100644 index 0000000..bdd6b70 --- /dev/null +++ b/audit/acceptance/ablations/README.md @@ -0,0 +1,44 @@ +# Load-bearing mechanism ablations + +These receipts answer the Distill question: does each new mechanism have a +real measured consumer, or is it complexity the final combination happens to +carry? + +Each patch removes one fact from the accepted source: + +- [`origin.patch`](origin.patch) bypasses the exact common-byte origin gate. +- [`confirm.patch`](confirm.patch) disables variable-width raw confirmation. +- [`tags.patch`](tags.patch) ignores the pattern-tag byte returned by the + vector screen and rechecks every tag, matching the earlier Go replay shape. + +The variants preserve match semantics. `confirm.patch` intentionally makes the +direct test that requires the specialization fail, so the performance binary +is built with `-run '^$'` after the unmodified source has passed correctness. + +## Result + +| removed mechanism | measured consumer | Ice Lake | Sapphire Rapids | decision | +|---|---|---:|---:|---| +| common-byte origin gate | focused N=5 field rows | worst median 1.0008, worst sample 1.066 | worst median 1.0780, worst sample 1.085 | required | +| variable-width raw confirmation | five same-contract Rebar rows | 3/5 wins, worst 2.4758 | 3/5 wins, worst 2.4500 | required | +| returned pattern tags | five same-contract Rebar rows | 4/5 wins, worst 1.1876 | 5/5 wins, worst 0.9726 | required by the two-host bar | + +The synthetic N=1 miss row still wins without variable confirmation because it +has no survivors to confirm. The sparse N=5 miss rows also still win when Go +rechecks every pattern tag. Rebar enumeration is the consumer that makes both +pieces load-bearing. + +## Verify + +```sh +(cd audit/acceptance/ablations && sha256sum -c SHA256SUMS) +python3 audit/acceptance/ablations/summarize.py +git apply --unidiff-zero --check audit/acceptance/ablations/origin.patch +git apply --unidiff-zero --check audit/acceptance/ablations/confirm.patch +git apply --unidiff-zero --check audit/acceptance/ablations/tags.patch +``` + +[`field/`](field/) contains eight paired samples per focused row and host. +[`rebar/`](rebar/) contains three passes over the five same-contract rows per +variant and host. Both campaigns were pinned to core 2 and used the same native +fields as the accepted runs. diff --git a/audit/acceptance/ablations/SHA256SUMS b/audit/acceptance/ablations/SHA256SUMS new file mode 100644 index 0000000..ffc9560 --- /dev/null +++ b/audit/acceptance/ablations/SHA256SUMS @@ -0,0 +1,23 @@ +ab39b5f03a4df3c46d938a62332abd0f0fbbe7df1e8ca6fe9e28b00006d28146 ./README.md +a6cfec23d665591f7b02ac033851b0011ca82dbee3c4facf3b63be833875bc59 ./confirm.patch +fc70c4ee51dfd1e47501a49e4c077cdc90d69e5b90d3fa1c9a3377faa5d0c9a2 ./field/ice/confirm.txt +982080aa7abf060aa0468110311fa2918cae6de2776902510cb2c235c2b25dc8 ./field/ice/origin.txt +9b17f207a0ccb80c9b4bb8eeef736d0b29e7d4e3a0e18f53070e1c7404b3ef83 ./field/ice/tags.txt +315b4ce8e6ca25e781ede6f2fec8b6d8c0f11d23d97f4d7a34a2ac1fe1f7c1cd ./field/spr/confirm.txt +3deeb425c4275fc7c79330b1d950062bf24ad6e369f7b49f24103d4c38fbb1c0 ./field/spr/origin.txt +a87d0ebe5ef7f662849da283e72a96476c0f20a9bf2753b8b068da05f5f84c69 ./field/spr/tags.txt +7e54383c2fe4cfe75aa4e86ca5676be7d16532525f735720e57f559d35889498 ./origin.patch +1e78216c3691ecffde8077e5123f900d93bc98aa48044f8fbcc7acb554bedfaa ./rebar/ice/confirm-pass1.csv +075ced5309cbe345852998981ed09783a1cff39c9a92d7b5ebce0f020a725c67 ./rebar/ice/confirm-pass2.csv +d1e0ee286652abd1a5eb26a8c763b021bf9ec752cb20f5f691723f45bc785538 ./rebar/ice/confirm-pass3.csv +ae57183bd92de71948c8074e755d3482a65574a65a5c5f7a238d6e19bebed6bd ./rebar/ice/tags-pass1.csv +f434df8f76f293cd8a726e6a6cae08df682d8bc21b3e9a4315bd024d3a9a70fb ./rebar/ice/tags-pass2.csv +69d1ed584ffd9f4a51bf5dc17e8ff830e660abeee53da99413f0820ba4e263a8 ./rebar/ice/tags-pass3.csv +07b08362b718f4097930ed81d7f61957396abba6a9d82eb63bb2b63f435ca344 ./rebar/spr/confirm-pass1.csv +45e7613914ebee510f91e237636e6ef443cf99ee487519a43bd4a77730f25a31 ./rebar/spr/confirm-pass2.csv +2934c52865ff2f4cfe263f129a6148991a8216f3e01453b4ef0cd34de86f6980 ./rebar/spr/confirm-pass3.csv +33026f40833675df446dc43f0aabd959a541cce2e0eea86dddc40714eac0e70a ./rebar/spr/tags-pass1.csv +3702d5e8cf7efc95bf64afa63fb0eeb7691d55608a9d4da2b10f3766042eb535 ./rebar/spr/tags-pass2.csv +85b53524fd6228ed350cd2fa484d6ad38cbec4d4cd21e48c35994e11ea87d4b9 ./rebar/spr/tags-pass3.csv +91da810df6d832fb2348db4a2589f2b46ff6174e3a09382c5c6563ccfd2fddcc ./summarize.py +4230f56bf42ea045adb1b4171e3f1840da9ff09ed696858c0bf817b0cfc8ce2c ./tags.patch diff --git a/audit/acceptance/ablations/confirm.patch b/audit/acceptance/ablations/confirm.patch new file mode 100644 index 0000000..a89f7ce --- /dev/null +++ b/audit/acceptance/ablations/confirm.patch @@ -0,0 +1,6 @@ +diff --git a/plan.go b/plan.go +--- a/plan.go ++++ b/plan.go +@@ -1482,2 +1482,0 @@ +- p.singlePayload = string(confirm) +- } else if confirm := makeUnicodePairVariableConfirm(pattern, anchor.at); confirm.valid() { diff --git a/audit/acceptance/ablations/field/ice/confirm.txt b/audit/acceptance/ablations/field/ice/confirm.txt new file mode 100644 index 0000000..f29b2c6 --- /dev/null +++ b/audit/acceptance/ablations/field/ice/confirm.txt @@ -0,0 +1,14 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 93111 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6777 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 87893 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6687 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 94080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6748 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 86450 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6701 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 104777 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6770 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 85433 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6744 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 86957 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6704 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 86283 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6704 x_vs_best +PASS +ok github.com/tsenart/casei/arena 16.668s diff --git a/audit/acceptance/ablations/field/ice/origin.txt b/audit/acceptance/ablations/field/ice/origin.txt new file mode 100644 index 0000000..0722e74 --- /dev/null +++ b/audit/acceptance/ablations/field/ice/origin.txt @@ -0,0 +1,22 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 210254 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.019 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 149071 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.004 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 200769 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9911 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 168193 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9753 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 311967 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.066 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 165406 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9982 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 246348 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.003 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 228288 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9986 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 134730 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9924 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 375010 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9911 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 303208 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9873 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 180797 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9847 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 184924 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9907 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 149559 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9938 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 172730 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.002 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 182277 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9927 x_vs_best +PASS +ok github.com/tsenart/casei/arena 139.418s diff --git a/audit/acceptance/ablations/field/ice/tags.txt b/audit/acceptance/ablations/field/ice/tags.txt new file mode 100644 index 0000000..1b3943b --- /dev/null +++ b/audit/acceptance/ablations/field/ice/tags.txt @@ -0,0 +1,22 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 199544 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9369 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 173610 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9261 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 153365 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8832 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 148690 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9592 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 149820 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9275 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 165410 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9484 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 203993 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9392 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 161115 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8517 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 194817 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9186 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 214277 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9370 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 144909 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9491 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 199769 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9033 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 129929 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8783 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155594 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9102 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 183309 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9099 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 197978 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9524 x_vs_best +PASS +ok github.com/tsenart/casei/arena 139.315s diff --git a/audit/acceptance/ablations/field/spr/confirm.txt b/audit/acceptance/ablations/field/spr/confirm.txt new file mode 100644 index 0000000..47840c9 --- /dev/null +++ b/audit/acceptance/ablations/field/spr/confirm.txt @@ -0,0 +1,14 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 75255 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7014 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 73699 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6982 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 73409 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7125 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 73140 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7075 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 74102 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7060 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 73444 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7053 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 75045 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7108 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 1 75463 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7144 x_vs_best +PASS +ok github.com/tsenart/casei/arena 16.305s diff --git a/audit/acceptance/ablations/field/spr/origin.txt b/audit/acceptance/ablations/field/spr/origin.txt new file mode 100644 index 0000000..5cb17a4 --- /dev/null +++ b/audit/acceptance/ablations/field/spr/origin.txt @@ -0,0 +1,22 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 175577 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.052 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 182827 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.068 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 182032 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.078 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 175397 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.085 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 175428 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.062 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 184470 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.078 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 174412 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.081 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 182194 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.081 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 174694 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.066 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 182278 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.069 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175441 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.080 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175283 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.071 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175185 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.065 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175006 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.079 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175156 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.068 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175504 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.080 x_vs_best +PASS +ok github.com/tsenart/casei/arena 145.511s diff --git a/audit/acceptance/ablations/field/spr/tags.txt b/audit/acceptance/ablations/field/spr/tags.txt new file mode 100644 index 0000000..817424c --- /dev/null +++ b/audit/acceptance/ablations/field/spr/tags.txt @@ -0,0 +1,22 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 162735 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9717 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 155423 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9711 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 170325 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9714 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 162307 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9692 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 162897 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9722 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 162963 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9716 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 162112 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9704 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 155020 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9713 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155391 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9621 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 167951 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9639 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155953 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9643 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155759 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9613 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 156188 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9672 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155606 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9639 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 156074 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9650 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 155799 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9787 x_vs_best +PASS +ok github.com/tsenart/casei/arena 145.672s diff --git a/audit/acceptance/ablations/origin.patch b/audit/acceptance/ablations/origin.patch new file mode 100644 index 0000000..087bc57 --- /dev/null +++ b/audit/acceptance/ablations/origin.patch @@ -0,0 +1,7 @@ +diff --git a/plan.go b/plan.go +--- a/plan.go ++++ b/plan.go +@@ -2375,3 +2375,0 @@ +- if len(haystack) >= 4096 && p.rawByteOrigin.usable() { +- return withZeroWidth(p.findRawByteOrigin(haystack)) +- } diff --git a/audit/acceptance/ablations/rebar/ice/confirm-pass1.csv b/audit/acceptance/ablations/rebar/ice/confirm-pass1.csv new file mode 100644 index 0000000..2103f5a --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/confirm-pass1.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,501.96ms,385.63us,2.60us,388.64us,13.79us,376.29us,505.85us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,405.24ms,336.99us,6.04us,350.19us,38.46us,324.08us,793.40us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,203.56ms,156.77us,1.57us,159.94us,26.43us,153.98us,0.96ms +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,354.09ms,287.49us,4.52us,291.12us,31.58us,282.10us,1.01ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,949,802.22ms,522.16us,6.10us,526.48us,24.70us,506.74us,861.91us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,841,603.84ms,592.94us,3.67us,594.91us,10.26us,581.70us,693.94us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,53,754.05ms,9.46ms,65.76us,9.45ms,112.73us,9.26ms,9.72ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,335,703.93ms,1.49ms,11.62us,1.49ms,51.53us,1.46ms,2.14ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.32ms,60.19us,444.00ns,62.05us,7.01us,59.20us,172.64us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.59ms,82.12us,57.00ns,82.80us,1.93us,81.94us,108.14us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.87ms,80.29us,135.00ns,81.81us,6.98us,80.03us,280.35us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.17ms,61.60us,242.00ns,62.20us,2.16us,60.76us,90.38us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.57ms,82.08us,65.00ns,83.77us,14.69us,81.89us,530.48us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.92ms,80.58us,145.00ns,83.76us,25.15us,80.32us,573.70us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.21ms,61.19us,270.00ns,62.13us,2.90us,60.29us,91.18us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,52.78ms,44.80us,91.00ns,45.37us,1.79us,44.41us,69.77us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.51ms,80.26us,86.00ns,81.71us,6.24us,80.01us,172.68us diff --git a/audit/acceptance/ablations/rebar/ice/confirm-pass2.csv b/audit/acceptance/ablations/rebar/ice/confirm-pass2.csv new file mode 100644 index 0000000..fbfa447 --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/confirm-pass2.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,501.66ms,391.91us,5.42us,394.57us,16.05us,382.10us,668.57us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,403.66ms,336.43us,5.29us,339.97us,40.19us,325.78us,1.53ms +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,202.58ms,156.08us,1.12us,159.75us,12.11us,154.31us,304.65us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.10ms,290.09us,4.52us,290.50us,14.05us,283.61us,616.58us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,957,802.13ms,519.32us,2.74us,522.19us,13.92us,505.71us,722.12us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,839,604.96ms,592.44us,3.35us,595.87us,17.16us,582.26us,873.99us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,754.05ms,9.35ms,25.05us,9.38ms,117.97us,9.29ms,9.95ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,338,703.94ms,1.48ms,11.10us,1.48ms,27.52us,1.45ms,1.73ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.29ms,60.28us,218.00ns,60.93us,2.30us,59.46us,83.41us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.68ms,82.24us,115.00ns,83.81us,6.79us,81.95us,190.41us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.87ms,80.31us,64.00ns,81.11us,2.09us,80.10us,103.96us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.20ms,59.82us,199.00ns,61.36us,8.33us,59.06us,219.55us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,102.63ms,82.13us,102.00ns,83.86us,3.85us,81.93us,122.16us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.94ms,80.43us,203.00ns,82.28us,5.69us,80.08us,145.60us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.26ms,60.61us,234.00ns,61.42us,3.35us,59.62us,107.00us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,52.64ms,44.85us,75.00ns,45.31us,1.88us,44.56us,73.03us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.47ms,80.44us,60.00ns,81.39us,4.02us,80.20us,143.94us diff --git a/audit/acceptance/ablations/rebar/ice/confirm-pass3.csv b/audit/acceptance/ablations/rebar/ice/confirm-pass3.csv new file mode 100644 index 0000000..932c9b2 --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/confirm-pass3.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,501.61ms,388.36us,6.07us,390.23us,14.11us,377.35us,570.33us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,404.77ms,334.60us,5.37us,335.64us,11.60us,326.03us,599.77us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,202.63ms,156.86us,1.20us,160.12us,11.31us,154.66us,295.18us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.10ms,307.41us,3.25us,308.59us,5.68us,303.57us,362.59us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,956,802.08ms,520.19us,2.40us,522.35us,9.62us,507.99us,664.03us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,838,605.10ms,593.79us,3.81us,597.00us,16.75us,582.98us,862.68us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,754.04ms,9.37ms,25.17us,9.39ms,72.25us,9.31ms,9.65ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,339,703.96ms,1.47ms,10.36us,1.48ms,39.71us,1.45ms,2.05ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.23ms,60.32us,212.00ns,60.95us,2.07us,59.63us,80.02us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,102.66ms,82.27us,261.00ns,84.03us,8.60us,80.94us,324.44us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.96ms,80.59us,115.00ns,81.90us,4.16us,80.37us,142.33us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.20ms,60.80us,225.00ns,61.48us,2.39us,59.98us,83.57us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.55ms,82.32us,119.00ns,83.92us,7.80us,82.08us,311.62us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.94ms,80.82us,87.00ns,81.52us,1.98us,80.54us,106.37us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.25ms,59.80us,195.00ns,60.66us,3.82us,59.06us,137.35us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,102.36ms,44.93us,83.00ns,45.35us,1.66us,44.63us,66.99us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,104.02ms,80.44us,64.00ns,81.09us,1.85us,80.24us,102.53us diff --git a/audit/acceptance/ablations/rebar/ice/tags-pass1.csv b/audit/acceptance/ablations/rebar/ice/tags-pass1.csv new file mode 100644 index 0000000..0121481 --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/tags-pass1.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,251.50ms,134.83us,1.70us,137.53us,7.86us,131.79us,205.95us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,404.82ms,334.80us,3.99us,337.71us,20.08us,325.64us,827.43us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,202.61ms,158.01us,3.15us,162.39us,13.03us,153.40us,289.84us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.14ms,290.03us,3.90us,292.18us,24.26us,283.31us,913.78us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,704,802.32ms,706.39us,5.01us,710.09us,29.50us,688.16us,1.37ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,830,603.81ms,595.91us,4.55us,602.67us,56.10us,583.98us,1.59ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,754.02ms,9.36ms,26.19us,9.39ms,66.78us,9.31ms,9.61ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,336,703.91ms,1.48ms,12.20us,1.49ms,31.57us,1.46ms,1.76ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.25ms,28.93us,65.00ns,29.23us,1.43us,28.69us,50.10us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,102.72ms,82.12us,44.00ns,82.79us,1.89us,81.97us,115.91us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.91ms,80.51us,62.00ns,81.48us,3.68us,80.30us,130.65us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.18ms,29.11us,97.00ns,29.43us,1.56us,28.73us,50.31us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.60ms,82.41us,48.00ns,83.10us,1.91us,82.24us,105.70us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.90ms,80.66us,81.00ns,81.70us,6.17us,80.40us,223.13us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.18ms,29.18us,54.00ns,29.48us,1.38us,28.96us,49.04us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,52.65ms,44.99us,71.00ns,45.40us,1.60us,44.69us,67.44us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.47ms,80.63us,311.00ns,81.44us,3.60us,80.11us,136.51us diff --git a/audit/acceptance/ablations/rebar/ice/tags-pass2.csv b/audit/acceptance/ablations/rebar/ice/tags-pass2.csv new file mode 100644 index 0000000..aac52f8 --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/tags-pass2.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,251.37ms,135.08us,1.45us,137.20us,5.72us,132.55us,214.68us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,403.53ms,333.75us,4.46us,335.23us,8.68us,325.33us,409.24us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,202.53ms,156.39us,1.60us,158.41us,7.05us,153.55us,301.41us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.13ms,287.04us,3.87us,288.61us,10.54us,282.02us,493.27us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,706,802.10ms,705.72us,4.87us,708.11us,18.71us,688.91us,949.59us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,841,605.05ms,594.25us,4.94us,595.06us,12.17us,580.87us,721.70us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,754.08ms,9.32ms,30.26us,9.34ms,61.82us,9.26ms,9.53ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,337,703.90ms,1.48ms,11.48us,1.49ms,35.86us,1.45ms,1.78ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.28ms,29.24us,441.00ns,29.36us,1.62us,28.50us,48.26us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.67ms,82.28us,109.00ns,83.18us,2.03us,82.05us,107.44us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.90ms,80.43us,87.00ns,82.06us,6.75us,80.18us,163.19us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.38ms,28.88us,69.00ns,29.20us,1.64us,28.65us,54.01us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.39ms,82.05us,41.00ns,82.74us,2.17us,81.92us,106.86us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.90ms,80.68us,63.00ns,81.40us,2.26us,80.45us,110.44us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.19ms,29.02us,94.00ns,29.31us,1.46us,28.70us,50.76us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,52.74ms,44.82us,79.00ns,45.28us,1.81us,44.51us,69.46us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.74ms,80.48us,56.00ns,81.15us,2.10us,80.28us,110.24us diff --git a/audit/acceptance/ablations/rebar/ice/tags-pass3.csv b/audit/acceptance/ablations/rebar/ice/tags-pass3.csv new file mode 100644 index 0000000..98930ab --- /dev/null +++ b/audit/acceptance/ablations/rebar/ice/tags-pass3.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,251.42ms,134.67us,1.12us,136.72us,5.53us,132.25us,213.81us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,1000,404.75ms,336.30us,4.20us,338.04us,11.28us,325.55us,472.89us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,202.64ms,157.03us,1.56us,159.26us,5.22us,154.41us,240.63us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.09ms,287.69us,3.31us,289.41us,10.27us,282.92us,493.62us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,705,852.12ms,706.90us,5.01us,708.66us,12.80us,689.51us,841.48us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,1570556,840,605.11ms,593.08us,3.79us,595.16us,11.92us,581.48us,704.94us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,53,753.97ms,9.37ms,50.02us,9.46ms,159.96us,9.27ms,9.81ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,336,703.96ms,1.48ms,12.47us,1.49ms,33.30us,1.46ms,1.88ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.25ms,29.00us,57.00ns,29.34us,1.55us,28.76us,47.30us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,102.68ms,82.16us,58.00ns,82.88us,2.13us,81.98us,114.15us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.90ms,80.63us,50.00ns,81.25us,1.66us,80.44us,102.11us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.19ms,29.02us,52.00ns,29.35us,1.58us,28.83us,50.82us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-24,,613423,1000,104.64ms,82.09us,55.00ns,83.09us,3.30us,81.91us,133.26us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,103.90ms,80.78us,372.00ns,81.82us,5.32us,80.19us,175.25us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.21ms,28.75us,86.00ns,29.17us,1.77us,28.54us,51.20us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,52.63ms,45.02us,75.00ns,45.42us,1.48us,44.66us,61.05us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.49ms,80.38us,92.00ns,81.23us,3.91us,79.97us,149.44us diff --git a/audit/acceptance/ablations/rebar/spr/confirm-pass1.csv b/audit/acceptance/ablations/rebar/spr/confirm-pass1.csv new file mode 100644 index 0000000..9254690 --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/confirm-pass1.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,451.29ms,327.70us,3.68us,328.19us,6.37us,317.59us,415.96us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,450.88ms,364.72us,3.68us,365.11us,6.21us,354.82us,406.16us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.61ms,132.41us,875.00ns,134.46us,3.67us,131.36us,175.84us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,353.39ms,299.90us,2.78us,299.87us,4.67us,295.45us,356.91us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,982,801.30ms,502.01us,16.26us,509.04us,19.31us,479.00us,558.36us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,729,600.98ms,685.87us,4.39us,686.56us,7.55us,668.71us,719.23us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.58ms,9.39ms,12.88us,9.39ms,29.54us,9.35ms,9.49ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,305,701.16ms,1.64ms,10.67us,1.64ms,14.24us,1.62ms,1.68ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.43ms,52.40us,280.00ns,53.18us,2.43us,51.63us,70.41us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.52ms,94.66us,719.00ns,95.84us,3.10us,93.19us,131.88us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.44ms,83.44us,75.00ns,84.21us,1.95us,83.19us,102.15us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.40ms,51.20us,271.00ns,51.95us,2.42us,50.48us,69.39us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.48ms,94.34us,605.00ns,95.57us,3.20us,92.87us,121.42us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.40ms,83.67us,146.00ns,84.40us,1.92us,83.33us,107.88us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.29ms,51.18us,401.00ns,51.96us,2.55us,50.27us,76.76us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.33ms,36.02us,79.00ns,36.38us,1.68us,35.73us,72.24us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.34ms,83.58us,65.00ns,84.30us,1.79us,83.34us,98.34us diff --git a/audit/acceptance/ablations/rebar/spr/confirm-pass2.csv b/audit/acceptance/ablations/rebar/spr/confirm-pass2.csv new file mode 100644 index 0000000..f60bdd5 --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/confirm-pass2.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,451.25ms,324.41us,3.52us,324.70us,5.76us,315.31us,362.99us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,450.88ms,365.32us,3.76us,365.75us,5.96us,355.36us,406.67us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,201.47ms,132.41us,688.00ns,134.06us,3.34us,131.16us,167.25us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.74ms,301.55us,2.80us,301.18us,3.57us,297.10us,323.38us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,996,801.32ms,493.76us,6.88us,501.89us,18.18us,478.99us,553.91us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,731,601.84ms,683.93us,4.12us,684.55us,7.23us,668.11us,727.65us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.00ms,9.37ms,19.40us,9.39ms,37.52us,9.34ms,9.51ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,306,701.08ms,1.63ms,9.55us,1.64ms,14.33us,1.62ms,1.69ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.39ms,53.48us,258.00ns,54.34us,2.67us,52.46us,74.81us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.48ms,94.42us,608.00ns,95.33us,2.53us,93.04us,127.81us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.42ms,83.19us,77.00ns,83.92us,1.83us,82.94us,102.33us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.39ms,51.19us,151.00ns,51.97us,2.42us,50.54us,71.65us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.41ms,94.37us,554.00ns,95.63us,3.08us,93.18us,121.76us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.38ms,83.39us,67.00ns,84.11us,1.74us,83.16us,98.78us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.32ms,51.60us,196.00ns,52.36us,2.53us,50.69us,72.60us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.31ms,36.08us,85.00ns,36.42us,1.39us,35.81us,53.58us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.35ms,83.33us,88.00ns,84.04us,1.75us,83.04us,99.21us diff --git a/audit/acceptance/ablations/rebar/spr/confirm-pass3.csv b/audit/acceptance/ablations/rebar/spr/confirm-pass3.csv new file mode 100644 index 0000000..5b3ecf0 --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/confirm-pass3.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,451.28ms,322.69us,3.73us,323.11us,5.66us,313.87us,361.34us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,450.90ms,364.88us,3.65us,365.36us,6.22us,355.70us,407.85us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.58ms,135.84us,629.00ns,136.99us,2.66us,134.33us,161.30us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.71ms,301.53us,2.83us,300.97us,3.71us,296.74us,324.83us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,981,801.97ms,498.25us,10.98us,509.27us,20.35us,482.67us,571.27us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,728,602.02ms,686.29us,4.50us,687.26us,8.03us,669.87us,736.19us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.06ms,9.38ms,19.07us,9.40ms,33.98us,9.35ms,9.49ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,305,701.10ms,1.63ms,7.80us,1.64ms,14.27us,1.62ms,1.70ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.37ms,53.50us,323.00ns,54.31us,2.65us,52.64us,79.25us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.49ms,94.94us,732.00ns,96.14us,3.12us,93.04us,127.07us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.42ms,83.43us,92.00ns,84.26us,1.91us,83.14us,102.10us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.37ms,51.71us,254.00ns,52.49us,2.66us,50.75us,85.32us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.47ms,94.33us,623.00ns,95.65us,3.55us,93.13us,151.58us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.44ms,83.85us,87.00ns,84.59us,1.81us,83.59us,105.37us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,101.29ms,50.66us,179.00ns,51.45us,2.74us,50.00us,90.79us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.36ms,35.99us,89.00ns,36.34us,1.34us,35.70us,53.51us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.39ms,83.45us,88.00ns,84.22us,2.08us,83.12us,106.09us diff --git a/audit/acceptance/ablations/rebar/spr/tags-pass1.csv b/audit/acceptance/ablations/rebar/spr/tags-pass1.csv new file mode 100644 index 0000000..b6ec736 --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/tags-pass1.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,200.98ms,122.21us,1.32us,123.50us,3.58us,118.78us,143.06us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.74ms,364.15us,3.75us,364.48us,6.08us,355.16us,420.06us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.54ms,135.57us,3.02us,135.19us,3.57us,131.16us,175.56us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.73ms,301.27us,2.84us,300.90us,3.60us,296.86us,326.48us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,755,851.31ms,661.90us,3.40us,662.39us,5.60us,649.76us,685.02us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,732,601.93ms,682.28us,4.01us,683.24us,7.07us,668.07us,725.92us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.65ms,9.39ms,24.04us,9.40ms,40.25us,9.31ms,9.51ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,304,701.15ms,1.64ms,10.66us,1.64ms,13.97us,1.62ms,1.69ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.36ms,24.22us,71.00ns,24.61us,1.77us,23.91us,38.86us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,151.30ms,94.30us,536.00ns,95.23us,2.46us,93.04us,116.86us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.62us,79.00ns,84.37us,2.00us,83.36us,106.70us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.38ms,24.85us,142.00ns,25.31us,1.82us,24.61us,40.53us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.48ms,94.54us,716.00ns,95.88us,3.22us,93.20us,118.45us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.40ms,83.39us,66.00ns,84.16us,2.04us,83.10us,101.45us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.34ms,23.91us,85.00ns,24.38us,1.99us,23.64us,43.77us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.30ms,36.04us,99.00ns,36.48us,1.93us,35.73us,65.17us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.34ms,83.41us,69.00ns,84.19us,2.04us,83.18us,98.83us diff --git a/audit/acceptance/ablations/rebar/spr/tags-pass2.csv b/audit/acceptance/ablations/rebar/spr/tags-pass2.csv new file mode 100644 index 0000000..635ca2a --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/tags-pass2.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,200.96ms,122.46us,2.55us,123.67us,4.36us,117.08us,151.06us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,450.85ms,365.64us,3.82us,365.97us,5.97us,356.15us,416.56us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.60ms,135.00us,503.00ns,136.35us,2.83us,133.83us,157.91us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.71ms,300.74us,2.78us,300.54us,3.77us,296.08us,337.20us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,752,852.69ms,664.10us,3.34us,664.42us,5.67us,652.49us,708.63us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,732,601.09ms,682.84us,4.13us,683.80us,7.66us,666.40us,727.67us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.09ms,9.39ms,17.03us,9.39ms,28.77us,9.35ms,9.47ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,305,701.09ms,1.64ms,9.36us,1.64ms,14.64us,1.61ms,1.68ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.36ms,23.70us,115.00ns,24.43us,1.88us,23.49us,43.36us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.44ms,94.54us,666.00ns,95.80us,3.58us,92.88us,138.13us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.59us,76.00ns,84.35us,2.11us,83.29us,112.65us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.33ms,23.98us,98.00ns,24.37us,1.79us,23.62us,44.38us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.47ms,94.20us,583.00ns,95.42us,3.17us,92.80us,123.02us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.28us,75.00ns,84.08us,2.02us,83.04us,102.03us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.33ms,24.25us,201.00ns,24.60us,1.81us,23.65us,42.35us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.31ms,36.10us,74.00ns,36.48us,1.67us,35.86us,69.29us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.35ms,83.56us,73.00ns,84.27us,1.79us,83.27us,98.13us diff --git a/audit/acceptance/ablations/rebar/spr/tags-pass3.csv b/audit/acceptance/ablations/rebar/spr/tags-pass3.csv new file mode 100644 index 0000000..b02b47f --- /dev/null +++ b/audit/acceptance/ablations/rebar/spr/tags-pass3.csv @@ -0,0 +1,18 @@ +name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,200.95ms,122.19us,1.51us,123.51us,3.89us,118.91us,146.55us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,450.88ms,364.73us,3.88us,364.99us,6.13us,355.55us,414.63us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.59ms,135.24us,800.00ns,136.52us,3.16us,133.75us,160.56us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.74ms,301.17us,2.92us,301.11us,4.86us,296.86us,381.45us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,751,851.72ms,664.78us,3.27us,665.44us,5.45us,653.01us,684.56us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,731,601.63ms,682.79us,4.44us,684.00us,7.92us,667.96us,727.70us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.13ms,9.38ms,17.07us,9.39ms,38.33us,9.32ms,9.49ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,306,701.08ms,1.63ms,7.71us,1.64ms,14.73us,1.62ms,1.69ms +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.31ms,23.71us,51.00ns,24.11us,1.69us,23.53us,38.87us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.46ms,94.65us,595.00ns,95.71us,2.79us,93.23us,119.46us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.38ms,83.69us,88.00ns,84.44us,2.22us,83.30us,118.86us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.32ms,23.49us,65.00ns,23.96us,1.95us,23.30us,42.31us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.43ms,94.31us,485.00ns,95.56us,3.02us,93.27us,121.35us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.38ms,83.44us,74.00ns,84.20us,2.05us,83.19us,112.67us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.31ms,23.95us,140.00ns,24.50us,1.91us,23.73us,48.58us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.31ms,36.14us,88.00ns,36.49us,1.66us,35.82us,73.65us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.37ms,83.49us,85.00ns,84.25us,1.98us,83.21us,101.05us diff --git a/audit/acceptance/ablations/summarize.py b/audit/acceptance/ablations/summarize.py new file mode 100644 index 0000000..3c43f46 --- /dev/null +++ b/audit/acceptance/ablations/summarize.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +"""Verify and summarize the three two-host publication ablations.""" + +from collections import defaultdict +import csv +from pathlib import Path +from statistics import median +import re +import sys + + +sys.dont_write_bytecode = True +ROOT = Path(__file__).resolve().parent +HOSTS = ("ice", "spr") +VARIANTS = ("origin", "confirm", "tags") +REBAR_ROWS = { + "curated/01-literal/sherlock-casei-ru", + "curated/02-literal-alternate/sherlock-casei-ru", + "hyperscan/literal-casei-russian-nosom", + "hyperscan/literal-casei-russian-som", + "opt/prefilter/literal-casei-russian", +} + + +def duration_ns(raw): + for suffix, scale in (("ns", 1), ("us", 1_000), ("ms", 1_000_000), ("s", 1_000_000_000)): + if raw.endswith(suffix): + return float(raw[:-len(suffix)]) * scale + raise ValueError(f"unrecognized duration {raw!r}") + + +def field_rows(host, variant): + path = ROOT / "field" / host / f"{variant}.txt" + rows = defaultdict(list) + with path.open() as source: + for line in source: + fields = line.split() + if not fields or not fields[0].startswith("BenchmarkBar/"): + continue + name = re.sub(r"-[0-9]+$", "", fields[0]) + try: + at = fields.index("x_vs_best") + ratio = float(fields[at - 1]) + except (ValueError, IndexError) as err: + raise SystemExit(f"{path}: malformed benchmark row") from err + rows[name].append(ratio) + expected_rows = 1 if variant == "confirm" else 2 + if len(rows) != expected_rows or any(len(values) != 8 for values in rows.values()): + raise SystemExit(f"{path}: expected {expected_rows} rows with eight samples, got {dict(rows)}") + return rows + + +def rebar_rows(host, variant): + ratios = defaultdict(list) + paths = sorted((ROOT / "rebar" / host).glob(f"{variant}-pass*.csv")) + if len(paths) != 3: + raise SystemExit(f"{host}/{variant}: expected three Rebar passes, found {len(paths)}") + for path in paths: + rows = defaultdict(dict) + with path.open(newline="") as source: + for row in csv.DictReader(source): + if row["err"]: + raise SystemExit(f"{path}: {row['name']}/{row['engine']}: {row['err']}") + rows[row["name"]][row["engine"]] = duration_ns(row["median"]) + if set(rows) != REBAR_ROWS: + raise SystemExit(f"{path}: wrong row inventory: {sorted(rows)}") + for name, engines in rows.items(): + casei = engines.pop("casei", None) + if casei is None or not engines: + raise SystemExit(f"{path}: {name}: missing casei or competitor") + ratios[name].append(casei / min(engines.values())) + return ratios + + +def main(): + print("Focused BenchmarkBar ablations (median of eight paired samples):") + for host in HOSTS: + for variant in VARIANTS: + rows = field_rows(host, variant) + values = [median(samples) for samples in rows.values()] + print( + f" {host}/{variant}: rows={len(values)}, " + f"wins={sum(value < 1 for value in values)}/{len(values)}, " + f"worst-median={max(values):.4f}, " + f"worst-sample={max(max(samples) for samples in rows.values()):.4f}" + ) + + print("Same-contract Rebar ablations (median of three passes):") + for host in HOSTS: + for variant in ("confirm", "tags"): + rows = rebar_rows(host, variant) + values = [median(samples) for samples in rows.values()] + print( + f" {host}/{variant}: wins={sum(value < 1 for value in values)}/5, " + f"worst={max(values):.4f}" + ) + + +if __name__ == "__main__": + main() diff --git a/audit/acceptance/ablations/tags.patch b/audit/acceptance/ablations/tags.patch new file mode 100644 index 0000000..f52d6fd --- /dev/null +++ b/audit/acceptance/ablations/tags.patch @@ -0,0 +1,5 @@ +diff --git a/raw_byte.go b/raw_byte.go +--- a/raw_byte.go ++++ b/raw_byte.go +@@ -654,0 +655 @@ ++ candidates = 0xff diff --git a/audit/acceptance/methodology/ice/sequential-focused.txt b/audit/acceptance/methodology/ice/sequential-focused.txt new file mode 100644 index 0000000..968ff9f --- /dev/null +++ b/audit/acceptance/methodology/ice/sequential-focused.txt @@ -0,0 +1,30 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 198497 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9801 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 151966 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.003 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 180033 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8265 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 168044 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.083 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 152869 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8597 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 151386 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8472 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 154648 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9773 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 175792 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8556 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 176423 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8938 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 184036 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8974 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 156566 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9990 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 150803 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9258 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 164199 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9631 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 168080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7516 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 180930 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8896 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 157069 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.001 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175779 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.020 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 272320 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9574 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 213419 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9901 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 187354 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9343 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 148195 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.125 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 180572 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7805 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 175528 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9903 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 165985 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9166 x_vs_best +PASS +ok github.com/tsenart/casei/arena 84.398s diff --git a/audit/acceptance/methodology/ice/sequential-windows.txt b/audit/acceptance/methodology/ice/sequential-windows.txt new file mode 100644 index 0000000..1203c9d --- /dev/null +++ b/audit/acceptance/methodology/ice/sequential-windows.txt @@ -0,0 +1,114 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/single/log_miss_1kb 30 270.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5855 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 266.3 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5850 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 259.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5840 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 4335 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6934 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 4244 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7055 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 4324 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7139 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 24040 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7110 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 23183 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7109 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 23732 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7048 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 27249 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2913 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 22564 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3116 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 25700 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3110 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 11307 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4192 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 7839 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4126 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 9292 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4132 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 3274 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7256 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 3275 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7414 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 3240 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7254 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 3262 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2951 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 3261 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2997 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 3329 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3016 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 3257 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5711 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 3258 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5667 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 3272 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5673 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 3274 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3011 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 3259 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3070 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 3271 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3036 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 47172 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2489 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 43060 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2469 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 41614 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2518 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 96262 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4872 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 96290 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4829 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 95964 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4846 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 33707 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5565 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 34776 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5809 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 36106 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5586 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 59.17 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8483 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 60.53 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8683 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 70.73 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8489 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 208.9 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7330 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 212.8 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7307 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 233.8 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7215 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 332.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6051 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 324.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6683 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 384.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6597 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 346.1 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6293 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 324.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6389 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 344.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6491 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 55978 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7402 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 55132 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7472 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 56174 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7689 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 55874 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8124 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 62980 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8066 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 61519 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7776 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 52482 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2938 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 51518 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2987 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 51450 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2946 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 583.5 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7896 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 288.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7663 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 291.3 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7886 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 4936 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7636 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 6243 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7570 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 5068 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7523 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 2934 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5526 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 3049 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5362 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 2926 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5352 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 11661 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.04035 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 9316 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.04035 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 9385 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.04040 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 80923 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7621 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 77195 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7675 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 77378 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7651 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 40242 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4307 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 39566 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4365 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 40817 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4319 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 6514 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6326 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 7539 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6475 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 8508 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6462 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 11107 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4897 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 6323 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5117 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 8363 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4853 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 7497 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3753 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6766 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3574 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6853 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3665 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 112817 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2734 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 113996 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2677 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 116077 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2691 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 92219 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6629 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 88279 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6684 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 101082 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6696 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 173076 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8419 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 165168 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8765 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 160509 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.002 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 139080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8382 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 168577 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 1.072 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 177183 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9888 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 29513 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4135 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 33380 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4077 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 30639 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4104 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 2080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4561 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1945 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4435 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 2009 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4467 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 75854 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2138 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 61128 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2248 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 65243 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2132 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 32183 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.08507 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 33559 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.08729 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 30281 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.08533 x_vs_best +PASS +ok github.com/tsenart/casei/arena 86.824s diff --git a/audit/acceptance/methodology/spr/sequential-focused.txt b/audit/acceptance/methodology/spr/sequential-focused.txt new file mode 100644 index 0000000..07bc110 --- /dev/null +++ b/audit/acceptance/methodology/spr/sequential-focused.txt @@ -0,0 +1,30 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 169298 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9644 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160810 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9599 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160567 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9610 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160384 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9625 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 159970 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9609 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160388 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9624 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 165969 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9601 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 161013 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9607 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 161382 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9611 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160778 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9592 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160615 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9588 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 1 160030 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9623 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 215414 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9514 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 215160 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9491 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 190621 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9510 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 163717 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9503 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 163632 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9535 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 161635 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9531 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 168368 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9520 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 162121 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9538 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 163241 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9498 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 162835 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9495 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 204266 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9524 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 1 191159 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9510 x_vs_best +PASS +ok github.com/tsenart/casei/arena 87.008s diff --git a/audit/acceptance/methodology/spr/sequential-windows.txt b/audit/acceptance/methodology/spr/sequential-windows.txt new file mode 100644 index 0000000..fadda6a --- /dev/null +++ b/audit/acceptance/methodology/spr/sequential-windows.txt @@ -0,0 +1,114 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/single/log_miss_1kb 30 163.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6503 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 156.5 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6563 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 146.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6470 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1313 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8637 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1300 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8623 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1306 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8779 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 18855 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8854 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 19307 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8654 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 18665 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8977 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18763 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3857 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18964 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3833 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18958 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3928 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4904 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5072 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4889 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4983 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4866 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5067 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1462 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8523 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1464 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8505 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1476 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8508 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1487 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4305 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1473 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4197 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1456 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4238 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1478 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6850 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1460 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6802 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1476 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6863 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1465 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4102 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1654 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4115 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1452 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4141 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 32854 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2811 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 32718 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2736 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 32875 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2788 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 89336 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5165 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 83426 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5115 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 90107 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5109 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 24673 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5162 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 24934 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5166 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 24108 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5097 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 40.93 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8246 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 39.73 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8246 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 39.20 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8245 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 171.4 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7113 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 146.3 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7127 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 141.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7133 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 187.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6355 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 182.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6344 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 167.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6320 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 161.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6418 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 160.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6401 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 157.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6411 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 41567 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6461 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 37934 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7981 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 38066 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6992 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 41317 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8533 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 46936 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8291 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 41419 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8202 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 65451 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5755 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 58287 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5082 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 58080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5036 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 260.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8365 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 224.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8365 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 267.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8311 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1935 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8055 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1933 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7961 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1912 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8044 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1145 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6654 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1168 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6760 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1148 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6702 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5084 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03884 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5175 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03849 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5242 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03838 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 67924 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7638 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 68667 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7670 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 68595 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7733 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 36050 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4837 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 36389 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4762 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 51855 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4767 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2498 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7961 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2460 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8003 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2543 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8000 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2795 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7234 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2482 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7036 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2571 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6961 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 7728 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4669 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6887 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4723 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6837 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4671 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 111099 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3798 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 108102 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3699 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 111190 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3814 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 73758 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6859 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 74080 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6908 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 75332 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6963 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 174248 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9565 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 166950 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9603 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 168990 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9601 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 167140 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9515 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 175118 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9512 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 170328 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9519 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 27547 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5815 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 28042 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5526 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 27941 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5529 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1815 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5929 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 2038 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5947 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1984 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5957 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 63103 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2537 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 63509 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2550 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 70365 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2540 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 33991 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1266 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 34110 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1269 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 33210 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1268 x_vs_best +PASS +ok github.com/tsenart/casei/arena 88.233s diff --git a/audit/acceptance/native-reachability.gdb b/audit/acceptance/native-reachability.gdb new file mode 100644 index 0000000..0023a22 --- /dev/null +++ b/audit/acceptance/native-reachability.gdb @@ -0,0 +1,29 @@ +# Run against a root test binary on an amd64 AVX-512F/BW/VBMI host. Each +# breakpoint disables itself after the first hit, leaving one HIT line per +# changed native entry. +set pagination off +set confirm off +set print thread-events off +set startup-with-shell off +break github.com/tsenart/casei.literalSkipExact64.abi0 +break github.com/tsenart/casei.pairPairConfirmVBMI64.abi0 +break github.com/tsenart/casei.rawByteMultiAnchorSkip64.abi0 +commands 1 +silent +printf "HIT 1\n" +disable 1 +continue +end +commands 2 +silent +printf "HIT 2\n" +disable 2 +continue +end +commands 3 +silent +printf "HIT 3\n" +disable 3 +continue +end +run -test.run ^(TestLiteralSkipExact64MatchesModel|TestUnicodePairVariableConfirm|TestRawByteMultiAnchorVBMISkip64MatchesTableModel)$ -test.count=1 diff --git a/audit/acceptance/results/ice/benchmarkbar.txt b/audit/acceptance/results/ice/benchmarkbar.txt new file mode 100644 index 0000000..76b0089 --- /dev/null +++ b/audit/acceptance/results/ice/benchmarkbar.txt @@ -0,0 +1,114 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) CPU @ 2.60GHz +BenchmarkBar/single/log_miss_1kb 30 94.10 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5742 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 98.20 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5736 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 98.57 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5742 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1207 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7196 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1201 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7280 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1204 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7189 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 20421 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7544 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 20489 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7481 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 19438 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7486 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 20180 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3175 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 20117 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3018 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 19658 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2827 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4807 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4132 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4698 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4122 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4577 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4112 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1246 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7521 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1258 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7458 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1238 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7554 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1254 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3036 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1256 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3057 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1260 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3028 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1253 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5616 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1246 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5608 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1246 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5607 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1246 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3059 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1262 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3026 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1249 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2988 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 39333 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2759 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 39042 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2775 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 39587 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2775 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 88025 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4898 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 87748 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4957 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 87590 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4934 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 28331 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5527 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 28497 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5501 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 28413 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5523 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 20.37 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8124 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 21.00 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8109 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 20.90 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8110 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 67.20 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7145 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 72.37 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7126 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 66.20 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7093 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 110.9 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6175 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 110.4 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6174 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 112.9 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6163 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 107.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6000 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 97.97 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6022 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 98.40 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6031 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 49357 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7860 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 49531 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7749 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 49624 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7761 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 57057 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8000 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 57041 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8130 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 57532 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8036 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 51438 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4265 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 51713 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4357 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 51750 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4420 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 150.2 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8306 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 151.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8193 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 151.5 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7956 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 2118 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7510 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 2113 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7550 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 2119 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7505 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 921.3 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5091 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 935.7 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5606 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 921.1 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5529 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 6096 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03797 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5950 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03797 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 6334 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03818 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 70149 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7647 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 71462 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7674 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 72187 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7735 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 34249 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4378 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 34261 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4378 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 34407 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4481 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2218 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6253 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2224 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6284 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2216 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6283 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2220 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4690 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2226 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4758 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2239 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4742 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6816 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3911 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6677 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3854 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6612 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3970 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 110606 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3414 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 108605 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3422 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 107612 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3382 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 85342 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6822 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 86077 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6792 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 85191 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6764 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 141246 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9582 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 141905 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9622 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 125222 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9646 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 173818 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9736 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 148247 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9579 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 134790 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9624 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 28392 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4202 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 29175 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4151 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 28556 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4197 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1858 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4448 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1860 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4406 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1859 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4405 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 60133 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2275 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 61805 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2294 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 60512 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2274 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 30607 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1158 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 30529 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1152 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 30653 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1148 x_vs_best +PASS +ok github.com/tsenart/casei/arena 265.158s diff --git a/audit/acceptance/results/ice/field-receipt.txt b/audit/acceptance/results/ice/field-receipt.txt new file mode 100644 index 0000000..63a6ba7 --- /dev/null +++ b/audit/acceptance/results/ice/field-receipt.txt @@ -0,0 +1,32 @@ +receipt_format: casei-native-field-v1 +source_commit: 5ab3cc8c1501a701bbd023a16d9d7da317a634ca +source_manifest: audit/acceptance/SOURCE_SHA256SUMS +source_manifest_sha256: 043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9 +vendor_id: GenuineIntel +cpu_family: 6 +cpu_model: 106 +cpu_model_name: Intel(R) Xeon(R) CPU @ 2.60GHz +lscpu_model_name: Intel(R) Xeon(R) CPU @ 2.60GHz +required_cpu_features: avx2 avx512f avx512bw avx512vbmi +go: go1.26.6 linux/amd64 +cpu_affinity: 2 + +benchmarkbar_field: Vectorscan 5.4.12, PCRE2 10.47, rure 0.2.5, rust/aho-corasick 1.1.5, StringZilla 5.1.2, veloz +benchmarkbar_command: taskset -c 2 go test -run '^$' -bench '^BenchmarkBar$' -benchtime 30x -count 3 +benchmarkbar_rows: 36 +benchmarkbar_passes: 3 +benchmarkbar_entrants: 5-7 +benchmarkbar_dispatch: casei=512-bit, Vectorscan=512-bit VBMI +benchmarkbar_output: audit/acceptance/results/ice/benchmarkbar.txt +benchmarkbar_sha256: a61c8ac9eaf3f548c54ff4c92aa2ce6d24f8d11fd2d55250a27965e513a7a32c + +rebar_commit: 463d00f31887e84c38467805b9e3122c314b9521 +rebar_field: Hyperscan 5.4.2, PCRE2 JIT 10.47, rust/regex 1.12.4 +rebar_hyperscan_source_commit: bc3b191ab56055e8560c7cdc161c289c4d76e3d2 +rebar_command: taskset -c 2 rebar measure -e '^(casei|hyperscan|pcre2/jit|rust/regex)$' -f '<18-row audit filter>' --max-warmup-iters 100 --max-warmup-time 200ms --max-iters 1000 --max-time 500ms +rebar_rows: 18 +rebar_passes: 3 +rebar_entrants: casei, hyperscan, pcre2/jit, rust/regex +rebar_pass1: audit/rebar/results/ice/rebar-audit-pass1.csv sha256=a37d4082e114e1ac6624d19f6ac216109d1812411822dbf5904fd75f9d6a7a11 +rebar_pass2: audit/rebar/results/ice/rebar-audit-pass2.csv sha256=cf7580a159b36ee04957f5ab67749f5b0ca2a2a18672509ed5a958e9460a6116 +rebar_pass3: audit/rebar/results/ice/rebar-audit-pass3.csv sha256=863f3430c07039fb270fbc2f3ea3800cfd8d94358195a8ec8898fac222e9f813 diff --git a/audit/acceptance/results/ice/gdb-native.txt b/audit/acceptance/results/ice/gdb-native.txt new file mode 100644 index 0000000..6b1e49e --- /dev/null +++ b/audit/acceptance/results/ice/gdb-native.txt @@ -0,0 +1,24 @@ +host: Ice Lake, GenuineIntel family 6 model 106 +go: go1.26.6 linux/amd64 +gdb: GNU gdb 15.1 +source checksum stream: 043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9 +command: gdb -q -batch -x audit/acceptance/native-reachability.gdb casei.test + +warning: File "/usr/local/go/src/runtime/runtime-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". +To enable execution of this file add + add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py +line to your configuration file "/home/ts_perfloop_com/.config/gdb/gdbinit". +To completely disable this security protection add + set auto-load safe-path / +line to your configuration file "/home/ts_perfloop_com/.config/gdb/gdbinit". +For more information about this security protection see the +"Auto-loading safe path" section in the GDB manual. E.g., run from the shell: + info "(gdb)Auto-loading safe path" +Breakpoint 1 at 0x5edb40: file /home/ts_perfloop_com/casei/root_amd64.s, line 196. +Breakpoint 2 at 0x5f0b80: file /home/ts_perfloop_com/casei/root_amd64.s, line 2982. +Breakpoint 3 at 0x5f0f00: file /home/ts_perfloop_com/casei/root_amd64.s, line 3211. +HIT 3 +HIT 1 +HIT 2 +PASS +[Inferior 1 (process 37824) exited normally] diff --git a/audit/acceptance/results/spr/benchmarkbar.txt b/audit/acceptance/results/spr/benchmarkbar.txt new file mode 100644 index 0000000..5a90da2 --- /dev/null +++ b/audit/acceptance/results/spr/benchmarkbar.txt @@ -0,0 +1,114 @@ +goos: linux +goarch: amd64 +pkg: github.com/tsenart/casei/arena +cpu: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +BenchmarkBar/single/log_miss_1kb 30 118.4 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6484 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 111.5 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6495 x_vs_best +BenchmarkBar/single/log_miss_1kb 30 116.8 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6490 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1278 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8507 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1282 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8321 x_vs_best +BenchmarkBar/single/log_miss_64kb 30 1293 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8362 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 18615 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8668 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 18584 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8626 x_vs_best +BenchmarkBar/single/log_miss_1mb 30 18580 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8790 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18594 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3852 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18632 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3826 x_vs_best +BenchmarkBar/single/prose_miss_1mb 30 18360 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3829 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4939 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4971 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4687 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4947 x_vs_best +BenchmarkBar/single/code_miss_256kb 30 4699 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4905 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1277 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8466 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1278 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8466 x_vs_best +BenchmarkBar/single/log_needle3_64kb 30 1282 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8543 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1326 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4161 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1276 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4196 x_vs_best +BenchmarkBar/single/log_needle8_64kb 30 1315 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.4114 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1284 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6852 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1275 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6841 x_vs_best +BenchmarkBar/single/log_needle16_64kb 30 1282 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6857 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1315 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3946 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1324 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3872 x_vs_best +BenchmarkBar/single/log_needle32_64kb 30 1312 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.3889 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 32778 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2724 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 33067 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2748 x_vs_best +BenchmarkBar/single/log_hit_sparse_1mb 30 32994 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.2741 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 80951 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5319 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 80877 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5295 x_vs_best +BenchmarkBar/single/prose_hit_dense_1mb 30 81351 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5339 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 23753 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5491 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 24152 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5472 x_vs_best +BenchmarkBar/single/code_hit_brackets_256kb 30 24403 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 6.000 competitors 7.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 1.000 rure_active 256.0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.5664 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 22.53 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8144 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 29.20 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8139 x_vs_best +BenchmarkBar/single/latency_match_start_1kb 30 15.53 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8143 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 91.77 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7079 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 87.97 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7076 x_vs_best +BenchmarkBar/single/latency_match_mid_1kb 30 92.47 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.7071 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 126.9 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6397 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 131.8 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6403 x_vs_best +BenchmarkBar/single/latency_match_end_1kb 30 130.5 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6406 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 256.4 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6413 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 129.0 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6423 x_vs_best +BenchmarkBar/single/latency_miss_1kb 30 126.6 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6427 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 37942 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7068 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 38120 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6958 x_vs_best +BenchmarkBar/single/ru_miss_1mb 30 38258 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6902 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 41223 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8285 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 40885 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8135 x_vs_best +BenchmarkBar/single/ru_hit_sparse_1mb 30 41082 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8273 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 57483 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5697 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 57745 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5724 x_vs_best +BenchmarkBar/single/kelvin_hazard_1mb 30 57484 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5755 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 164.9 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8320 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 163.3 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8206 x_vs_best +BenchmarkBar/single/ru_latency_miss_1kb 30 166.4 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.8221 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1888 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8043 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1893 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8134 x_vs_best +BenchmarkBar/single/periodic_miss_64kb 30 1889 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.8098 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1006 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6691 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1009 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6767 x_vs_best +BenchmarkBar/single/samechar_miss_64kb 30 1017 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.6736 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5256 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.04007 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5320 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.03938 x_vs_best +BenchmarkBar/single/torture_miss_64kb 30 5166 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 6.000 entrants 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 1.000 veloz_active 256.0 veloz_vector_bits 0.04012 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 69352 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7929 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 69036 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7968 x_vs_best +BenchmarkBar/multi/multi_N2_miss_log_1mb 30 67818 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7890 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 36046 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4873 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 36088 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4775 x_vs_best +BenchmarkBar/multi/multi_N8_miss_log_1mb 30 35698 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4863 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2414 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7805 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2343 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7879 x_vs_best +BenchmarkBar/multi/multi_N64_miss_log_64kb 30 2415 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7862 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2368 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6389 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2357 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6412 x_vs_best +BenchmarkBar/multi/multi_N512_miss_log_64kb 30 2412 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 5.000 competitors 7.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 1.000 rustac_active 256.0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6550 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 7022 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4713 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6910 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4718 x_vs_best +BenchmarkBar/multi/multi_N512_miss_hazard_64kb 30 6981 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.4619 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 107357 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3698 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 111273 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3849 x_vs_best +BenchmarkBar/multi/multi_N8_hit_log_1mb 30 110634 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 6.000 entrants 1.000 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.3838 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 73716 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7140 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 74056 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.7136 x_vs_best +BenchmarkBar/multi/multi_N1_unicode_pair_miss_1_5mb 30 74202 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.6944 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 156984 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9716 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 157734 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9799 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_miss_5mb 30 157026 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9707 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 157168 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9623 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 157961 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9641 x_vs_best +BenchmarkBar/multi/multi_N5_raw_transition_late_hit_5mb 30 157563 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.9639 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 27136 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5635 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 26961 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5619 x_vs_best +BenchmarkBar/multi/multi_N8_miss_ru_1mb 30 27147 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5543 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1815 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5948 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1810 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5989 x_vs_best +BenchmarkBar/multi/multi_N64_miss_ru_64kb 30 1974 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.5910 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 57269 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2641 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 58548 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2797 x_vs_best +BenchmarkBar/multi/multi_N8_miss_hazard_1mb 30 57009 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.2636 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 28632 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1300 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 28987 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1297 x_vs_best +BenchmarkBar/multi/multi_N8_hazard_hit_1mb 30 28778 ns/op 1.000 candidate_active 512.0 candidate_vector_bits 4.000 competitors 5.000 entrants 0 go_ac_active 0 go_ac_vector_bits 1.000 pcre2_active 128.0 pcre2_vector_bits 1.000 regexp_active 0 regexp_vector_bits 0 rure_active 0 rure_vector_bits 0 rustac_active 0 rustac_vector_bits 1.000 stringzilla_active 512.0 stringzilla_vector_bits 1.000 vectorscan_active 1.000 vectorscan_vbmi 512.0 vectorscan_vector_bits 0 veloz_active 0 veloz_vector_bits 0.1297 x_vs_best +PASS +ok github.com/tsenart/casei/arena 274.078s diff --git a/audit/acceptance/results/spr/field-receipt.txt b/audit/acceptance/results/spr/field-receipt.txt new file mode 100644 index 0000000..95c0c9b --- /dev/null +++ b/audit/acceptance/results/spr/field-receipt.txt @@ -0,0 +1,32 @@ +receipt_format: casei-native-field-v1 +source_commit: 5ab3cc8c1501a701bbd023a16d9d7da317a634ca +source_manifest: audit/acceptance/SOURCE_SHA256SUMS +source_manifest_sha256: 043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9 +vendor_id: GenuineIntel +cpu_family: 6 +cpu_model: 143 +cpu_model_name: Intel(R) Xeon(R) Platinum 8481C CPU @ 2.70GHz +lscpu_model_name: unknown (KVM virtualized CPUID) +required_cpu_features: avx2 avx512f avx512bw avx512vbmi +go: go1.26.6 linux/amd64 +cpu_affinity: 2 + +benchmarkbar_field: Vectorscan 5.4.12, PCRE2 10.47, rure 0.2.5, rust/aho-corasick 1.1.5, StringZilla 5.1.2, veloz +benchmarkbar_command: taskset -c 2 go test -run '^$' -bench '^BenchmarkBar$' -benchtime 30x -count 3 +benchmarkbar_rows: 36 +benchmarkbar_passes: 3 +benchmarkbar_entrants: 5-7 +benchmarkbar_dispatch: casei=512-bit, Vectorscan=512-bit VBMI +benchmarkbar_output: audit/acceptance/results/spr/benchmarkbar.txt +benchmarkbar_sha256: 11d05c54a7930a67cc1a2cefabd73ccb42bbdcfc77429fbc64f8158e9a244f94 + +rebar_commit: 463d00f31887e84c38467805b9e3122c314b9521 +rebar_field: Hyperscan 5.4.2, PCRE2 JIT 10.47, rust/regex 1.12.4 +rebar_hyperscan_source_commit: bc3b191ab56055e8560c7cdc161c289c4d76e3d2 +rebar_command: taskset -c 2 rebar measure -e '^(casei|hyperscan|pcre2/jit|rust/regex)$' -f '<18-row audit filter>' --max-warmup-iters 100 --max-warmup-time 200ms --max-iters 1000 --max-time 500ms +rebar_rows: 18 +rebar_passes: 3 +rebar_entrants: casei, hyperscan, pcre2/jit, rust/regex +rebar_pass1: audit/rebar/results/spr/rebar-audit-pass1.csv sha256=c9221b1d036dfbfb7ada9ce3d2ec2be1236fae0627a7508327dc461bb65a6909 +rebar_pass2: audit/rebar/results/spr/rebar-audit-pass2.csv sha256=f5abea61e8f766190b8f360f16f6f786e48cffcdd4aef9764ff8a0a119fa94df +rebar_pass3: audit/rebar/results/spr/rebar-audit-pass3.csv sha256=bfea805d4c64fa9b6596e279ea35439ae1a18bf94be97cac884065b8537b86eb diff --git a/audit/acceptance/results/spr/gdb-native.txt b/audit/acceptance/results/spr/gdb-native.txt new file mode 100644 index 0000000..c56cc45 --- /dev/null +++ b/audit/acceptance/results/spr/gdb-native.txt @@ -0,0 +1,24 @@ +host: Sapphire Rapids, GenuineIntel family 6 model 143 +go: go1.26.6 linux/amd64 +gdb: GNU gdb 15.1 +source checksum stream: 043dd919faa1d34cb26f2993f5f756e7f3265a10291e5889eecab67530cb27e9 +command: gdb -q -batch -x audit/acceptance/native-reachability.gdb casei.test + +warning: File "/usr/local/go/src/runtime/runtime-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load". +To enable execution of this file add + add-auto-load-safe-path /usr/local/go/src/runtime/runtime-gdb.py +line to your configuration file "/home/tomas/.config/gdb/gdbinit". +To completely disable this security protection add + set auto-load safe-path / +line to your configuration file "/home/tomas/.config/gdb/gdbinit". +For more information about this security protection see the +"Auto-loading safe path" section in the GDB manual. E.g., run from the shell: + info "(gdb)Auto-loading safe path" +Breakpoint 1 at 0x5edb40: file /home/tomas/casei-pr10-spr-0823.9nVjRd/casei/root_amd64.s, line 196. +Breakpoint 2 at 0x5f0b80: file /home/tomas/casei-pr10-spr-0823.9nVjRd/casei/root_amd64.s, line 2982. +Breakpoint 3 at 0x5f0f00: file /home/tomas/casei-pr10-spr-0823.9nVjRd/casei/root_amd64.s, line 3211. +HIT 3 +HIT 1 +HIT 2 +PASS +[Inferior 1 (process 16326) exited normally] diff --git a/audit/acceptance/summarize.py b/audit/acceptance/summarize.py new file mode 100644 index 0000000..e8a6f29 --- /dev/null +++ b/audit/acceptance/summarize.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +"""Verify and summarize the current two-host acceptance receipts.""" + +import hashlib +from pathlib import Path +from statistics import median +import sys + + +sys.dont_write_bytecode = True +SCRIPTS = Path(__file__).resolve().parents[2] / "scripts" +sys.path.insert(0, str(SCRIPTS)) +import verify_benchmarkbar # noqa: E402 + + +ROOT = Path(__file__).resolve().parent / "results" +SOURCE_MANIFEST = Path(__file__).resolve().parent / "SOURCE_SHA256SUMS" +HOSTS = {"ice": "Ice Lake", "spr": "Sapphire Rapids"} + + +def main(): + source_digest = hashlib.sha256(SOURCE_MANIFEST.read_bytes()).hexdigest() + for host, title in HOSTS.items(): + path = ROOT / host / "benchmarkbar.txt" + try: + verify_benchmarkbar.verify(path, expected_samples=3) + except verify_benchmarkbar.VerificationError as err: + raise SystemExit(err) from err + rows = verify_benchmarkbar.parse(path) + + ratios = { + name: [sample["x_vs_best"] for sample in samples] + for name, samples in rows.items() + } + middle = {name: median(values) for name, values in ratios.items()} + worst_row = max(middle, key=middle.get) + worst_sample = max(value for values in ratios.values() for value in values) + speedup = median(1 / value for value in middle.values()) + entrants = [ + sample["entrants"] + for samples in rows.values() + for sample in samples + ] + native = (ROOT / host / "gdb-native.txt").read_text().splitlines() + required = { + "HIT 1", + "HIT 2", + "HIT 3", + "PASS", + f"source checksum stream: {source_digest}", + } + missing = required.difference(native) + if missing: + raise SystemExit( + f"{title} native receipt missing: {', '.join(sorted(missing))}" + ) + print( + f"{title}: rows={len(rows)}, samples={sum(map(len, rows.values()))}, " + f"worst-row={worst_row}, median-x={middle[worst_row]:.4f}, " + f"worst-sample={worst_sample:.4f}, median-speedup={speedup:.2f}x, " + f"entrants={int(min(entrants))}-{int(max(entrants))}, native=3/3" + ) + + +if __name__ == "__main__": + main() diff --git a/audit/publication/README.md b/audit/publication/README.md index 08ac74e..23ef07e 100644 --- a/audit/publication/README.md +++ b/audit/publication/README.md @@ -1,12 +1,14 @@ -# Publication verification +# Historical 33-row publication verification -This directory contains the fresh hardware checks used for the August 2026 -publication review. These three-pass runs on each pinned host are the source of -the per-row tables in the top-level README. Perfloop's public Case is separate: -it co-measured the pre-engine and final source in ten pairs with random -source-arm order, using the worst `x_vs_best` across all 33 rows as its metric. -The purpose of this run was to rebuild the field, check that every row still -passes, and isolate the two main speed mechanisms with the same compiled plans. +This directory preserves the first August 2026 publication review. It covers +the 33-row board before the three Rebar-derived rows were added. The current +36-row claim and its raw transcripts live in +[`audit/acceptance/`](../acceptance/README.md). + +Perfloop's original public Case co-measured the pre-engine and final source in +ten pairs with random source-arm order, using the worst `x_vs_best` across all +33 rows as its metric. This historical run rebuilt that field, checked every +row, and isolated the two main speed mechanisms with the same compiled plans. The search source was commit `781eb8c36413f9a23c2d1f279ad9ef6554cac8bf`. The publication review then @@ -79,10 +81,11 @@ and AVX2 plus AVX-512 disabled. The complete pinned arena agreement and dispatch suite passed on both hosts. `FuzzIndexFold` and `FuzzMatcher` each ran for 30 seconds on both hosts. -The amd64 source now contains 36 linked assembly entry points. One-shot GDB -breakpoints observed all 36 across the normal, AVX-512-disabled, and -BMI2-disabled test runs. Before this check, `runSkip32` and `runSkip64` were -unreferenced source and absent from the linked test binary; they were removed. +The amd64 source at the audited commit contained 36 linked assembly entry +points. One-shot GDB breakpoints observed all 36 across the normal, +AVX-512-disabled, and BMI2-disabled test runs. Before this check, `runSkip32` +and `runSkip64` were unreferenced source and absent from the linked test binary; +they were removed. [`asm-reachability.gdb`](asm-reachability.gdb) is the command file used for the check. The three files named `gdb-*.txt` in `results/ice` retain the `HIT` and final `PASS` lines captured from these runs: @@ -96,9 +99,10 @@ gdb -q -batch -ex 'set environment GODEBUG cpu.bmi2=off' \ -x audit/publication/asm-reachability.gdb ./casei.test ``` -The union of the reported breakpoint numbers must be 1 through 36, and each -test process must print `PASS`. `summarize.py` checks both conditions from the -captured receipts. +For that historical source, the union of the reported breakpoint numbers must +be 1 through 36, and each test process must print `PASS`. `summarize.py` checks +both conditions from the captured receipts. Current-kernel reachability lives +with the current acceptance record in [`audit/acceptance/`](../acceptance/README.md). ## Recompute the summaries diff --git a/audit/rebar/README.md b/audit/rebar/README.md index 0991951..b56bba0 100644 --- a/audit/rebar/README.md +++ b/audit/rebar/README.md @@ -1,22 +1,30 @@ # Rebar audit artifacts -This directory contains the adapter and aggregate measurements behind -[`REBAR.md`](../../REBAR.md). It is evidence for the boundary of the public -claim, not another favorable benchmark suite. - -- [`runner/main.go`](runner/main.go) is the exact adapter used on both hosts. - It compiles a `Matcher` once, enumerates non-overlapping matches by calling - `Find` on each remaining suffix, verifies each matched byte width, and emits - rebar's timing/count samples after reading its KLV request. -- [`prepare.py`](prepare.py) registers that runner on all 18 representable - performance workloads and all three relevant semantic checks in the pinned - rebar checkout. It refuses any other rebar commit. -- [`results/`](results/) contains all six rebar CSVs: three passes on Ice Lake - and three on Sapphire Rapids, plus their SHA-256 receipt file. -- [`summarize.py`](summarize.py) validates the receipts and recomputes every - ratio and summary in `REBAR.md`. - -Run the receipt calculation from any directory: +This directory contains the adapter and measurements behind +[`REBAR.md`](../../REBAR.md). + +The current receipts say: + +- `casei` wins all 5/5 rows with the same Unicode contract on both hosts; +- the worst same-contract ratio is 0.8794 on Ice Lake and 0.8999 on Sapphire + Rapids; +- across all 18 representable stress rows, including 13 ASCII-only contracts, + `casei` wins 9/18 on each host. + +## What is here + +- [`runner/main.go`](runner/main.go) compiles a `Matcher` once, validates full + non-overlapping enumeration against an independent simple-fold oracle, then + times `Matcher.Each` or a single `Matcher.Find` query with only a scalar sink. +- [`prepare.py`](prepare.py) registers that runner on all 18 performance rows + and three behavior checks in the pinned Rebar checkout. +- [`results/`](results/) contains three CSV passes from each host and their + SHA-256 receipt file. +- [`summarize.py`](summarize.py) validates the inventory and error columns, + selects the fastest competitor on each pass, and recomputes every ratio in + `REBAR.md`. + +Verify the checked-in record from any directory: ```sh (cd audit/rebar/results && sha256sum -c SHA256SUMS) @@ -25,17 +33,11 @@ python3 audit/rebar/summarize.py ## Reproduce on a qualifying Linux host -Check out casei and rebar as siblings. The audit files landed after the measured -casei commit, but the search implementation must still be byte-identical to -`3954dbe40e8e21c4c7b2e2716f22647dd7cd880c`; the first command below proves -that before rebar is prepared: +Check out `casei` and Rebar as siblings: ```sh git clone https://github.com/tsenart/casei.git git clone https://github.com/BurntSushi/rebar.git -git -C casei diff --exit-code \ - 3954dbe40e8e21c4c7b2e2716f22647dd7cd880c -- \ - casei.go matcher.go plan.go root_amd64.go root_amd64.s root_other.go go.mod go.sum git -C rebar checkout 463d00f31887e84c38467805b9e3122c314b9521 cd rebar python3 ../casei/audit/rebar/prepare.py @@ -43,32 +45,33 @@ cargo build --release --bin rebar ./target/release/rebar build -e '^(casei|hyperscan|pcre2/jit|rust/regex)$' ``` -`prepare.py` also omits the unused `pcre2posix.c` wrapper because this pinned -rebar snapshot lacks its header. The native PCRE2 API and JIT sources used by -the runner are unchanged. +`prepare.py` refuses any other Rebar commit. It also omits the unused +`pcre2posix.c` wrapper because this pinned snapshot lacks its header. Rebar's +native PCRE2 API and JIT sources are unchanged. -The exact performance selection is the 18 rows to which the script adds -`casei`. Run three passes using rebar's protocol, with 100 warm-up iterations -or 200 ms and 1,000 measured iterations or 500 ms. The checked-in CSVs were -produced with: +The exact 18-row selection is: ```sh -./target/release/rebar measure \ +filter='^(curated/(01-literal|02-literal-alternate)/sherlock-casei-(en|ru)|hyperscan/literal-casei-(english|russian)-(no)?som|imported/leipzig/(twain-insensitive|tom-sawyer-huckle-fin-insensitive)|imported/sherlock/(name-(sherlock|holmes|sherlock-holmes|alt3|alt5)-casei|the-casei)|opt/prefilter/literal-casei-(english|russian))$' + +taskset -c 2 ./target/release/rebar measure \ -e '^(casei|hyperscan|pcre2/jit|rust/regex)$' \ - -f '^(curated/(01-literal|02-literal-alternate)/sherlock-casei-(en|ru)|hyperscan/literal-casei-(english|russian)-(no)?som|imported/leipzig/(twain-insensitive|tom-sawyer-huckle-fin-insensitive)|imported/sherlock/(name-(sherlock|holmes|sherlock-holmes|alt3|alt5)-casei|the-casei)|opt/prefilter/literal-casei-(english|russian))$' \ + -f "$filter" \ --max-warmup-iters 100 --max-warmup-time 200ms \ --max-iters 1000 --max-time 500ms > rebar-audit-pass1.csv ``` -Repeat for passes two and three. Rebar's runner validates every answer while -measuring; any mismatch appears in the CSV's `err` column. The two compatible -Unicode behavior checks can also be isolated with: +Repeat for passes two and three. The checked-in record used core 2 on both +hosts. The runner validates every answer in an untimed preflight; a mismatch +appears in the CSV `err` column and makes `summarize.py` fail. + +The compatible behavior checks can be run directly: ```sh -./target/release/rebar measure --verify --verbose -e '^casei$' \ +taskset -c 2 ./target/release/rebar measure --verify --verbose \ + -e '^casei$' \ -f '^test/unicode/case/(ascii-with-unicode|unicode)$' ``` -The excluded `test/unicode/case/ascii-only` check is intentionally not made to -pass: it expects `s` not to match `ſ`, contrary to casei's fixed Unicode -simple-fold contract. +The excluded `test/unicode/case/ascii-only` row expects `s` to miss `ſ`. +Unicode simple folding requires them to match. diff --git a/audit/rebar/results/SHA256SUMS b/audit/rebar/results/SHA256SUMS index d1b0d14..fb9bb8f 100644 --- a/audit/rebar/results/SHA256SUMS +++ b/audit/rebar/results/SHA256SUMS @@ -1,6 +1,6 @@ -d86cfe95cf7f21c3600a94d29e072f6d707ba56d649d72117bcbea16edc5a741 ice/rebar-audit-pass1.csv -c4ce41b8c89f0d7f59e9f55a1c06a665e0a6298d278c2010e5ae3b7a6039c504 ice/rebar-audit-pass2.csv -3c5f9a0ffe3f7da1292536c15f461f7746ca80f2f73b978a59f60d551c92669b ice/rebar-audit-pass3.csv -3d347e6131ea04c8df26839fdae29f90a9a375b888925973fafec05ab4d7ba7e spr/rebar-audit-pass1.csv -6a3cbf5bca2a347392c2c4541f480daf3686a7fe07b5cfa62372069914eef676 spr/rebar-audit-pass2.csv -70ffcf7125c9c5b132002cecaa7166f88fcbfdd499c66a21a0d061bf6f25b137 spr/rebar-audit-pass3.csv +a37d4082e114e1ac6624d19f6ac216109d1812411822dbf5904fd75f9d6a7a11 ice/rebar-audit-pass1.csv +cf7580a159b36ee04957f5ab67749f5b0ca2a2a18672509ed5a958e9460a6116 ice/rebar-audit-pass2.csv +863f3430c07039fb270fbc2f3ea3800cfd8d94358195a8ec8898fac222e9f813 ice/rebar-audit-pass3.csv +c9221b1d036dfbfb7ada9ce3d2ec2be1236fae0627a7508327dc461bb65a6909 spr/rebar-audit-pass1.csv +f5abea61e8f766190b8f360f16f6f786e48cffcdd4aef9764ff8a0a119fa94df spr/rebar-audit-pass2.csv +bfea805d4c64fa9b6596e279ea35439ae1a18bf94be97cac884065b8537b86eb spr/rebar-audit-pass3.csv diff --git a/audit/rebar/results/ice/rebar-audit-pass1.csv b/audit/rebar/results/ice/rebar-audit-pass1.csv index 1d22b68..1f9339a 100644 --- a/audit/rebar/results/ice/rebar-audit-pass1.csv +++ b/audit/rebar/results/ice/rebar-audit-pass1.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,351.38ms,272.24us,2.82us,273.22us,7.51us,259.58us,335.05us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.64ms,36.57us,648.00ns,37.01us,1.95us,35.43us,58.55us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.88ms,90.92us,1.44us,91.60us,3.11us,87.48us,111.94us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,201.06ms,134.28us,212.00ns,135.68us,2.83us,133.73us,163.05us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,451.51ms,397.32us,3.11us,398.94us,11.72us,382.79us,572.41us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.45ms,381.27us,1.88us,381.10us,4.50us,372.96us,408.00us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.90ms,155.26us,1.51us,157.08us,4.11us,152.94us,208.29us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.28ms,292.22us,3.00us,291.30us,4.20us,285.89us,318.09us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,888,601.48ms,561.48us,3.39us,562.66us,6.62us,545.84us,602.12us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.67ms,79.97us,110.00ns,81.03us,2.80us,79.68us,109.50us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,248,751.81ms,2.02ms,4.26us,2.02ms,8.05us,1.99ms,2.05ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.61ms,440.85us,1.46us,442.10us,6.44us,435.22us,550.59us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,74,751.89ms,6.80ms,19.43us,6.80ms,36.49us,6.73ms,7.02ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,722,601.57ms,692.02us,3.81us,693.30us,11.39us,680.91us,891.00us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.83ms,9.34ms,20.25us,9.34ms,32.23us,9.29ms,9.45ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,338,701.96ms,1.48ms,6.82us,1.48ms,11.73us,1.46ms,1.54ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.73ms,82.01us,456.00ns,82.86us,2.69us,79.01us,111.53us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.50ms,16.56us,25.00ns,16.80us,1.55us,16.46us,45.45us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.70ms,63.71us,54.00ns,64.39us,1.94us,63.56us,80.52us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.64ms,82.01us,453.00ns,82.82us,2.45us,79.30us,102.69us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.58ms,16.56us,28.00ns,16.81us,1.56us,16.45us,42.48us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.74ms,63.75us,54.00ns,64.38us,1.81us,63.58us,78.35us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.71ms,57.30us,160.00ns,58.04us,2.15us,56.50us,79.33us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.81ms,86.61us,231.00ns,87.59us,2.94us,86.22us,119.49us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.71ms,80.69us,61.00ns,81.59us,2.54us,80.42us,107.68us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.67ms,58.17us,148.00ns,59.05us,3.66us,57.49us,134.75us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.80ms,86.59us,162.00ns,87.53us,2.29us,86.30us,117.81us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.71ms,80.34us,77.00ns,81.22us,2.81us,79.99us,106.23us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,550,651.67ms,901.13us,26.85us,908.42us,43.25us,822.89us,1.24ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,702,601.70ms,704.01us,16.85us,712.76us,35.62us,644.90us,1.00ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,359,701.81ms,1.38ms,39.02us,1.40ms,85.28us,1.22ms,1.92ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,231,751.91ms,2.17ms,49.53us,2.17ms,80.53us,1.98ms,2.46ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,110,801.98ms,4.56ms,33.88us,4.55ms,49.99us,4.44ms,4.70ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,318,701.80ms,1.56ms,49.25us,1.58ms,116.42us,1.44ms,3.19ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,752.01ms,51.21ms,72.26us,51.27ms,135.53us,51.13ms,51.53ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,802.21ms,21.42ms,40.17us,21.68ms,445.03us,21.34ms,22.89ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.80ms,106.65us,1.30us,108.11us,5.37us,103.56us,212.95us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.71ms,67.80us,1.34us,68.26us,2.35us,65.26us,83.36us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.70ms,73.12us,60.00ns,73.88us,2.36us,72.88us,96.83us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.69ms,66.39us,297.00ns,67.42us,3.44us,65.57us,108.82us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.72ms,83.77us,2.07us,84.37us,3.30us,80.11us,110.48us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.85ms,108.02us,153.00ns,109.28us,3.36us,107.47us,138.31us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.81ms,117.69us,1.40us,120.42us,9.76us,114.43us,313.58us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.77ms,44.35us,299.00ns,44.87us,1.76us,43.46us,61.38us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.78ms,75.29us,53.00ns,76.03us,1.89us,75.10us,93.18us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.30ms,381.97us,4.70us,382.72us,6.46us,370.15us,421.75us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,199,751.88ms,2.52ms,10.66us,2.52ms,20.91us,2.49ms,2.68ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.54ms,491.67us,1.07us,492.75us,3.78us,486.60us,544.08us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.99ms,251.56us,3.12us,252.50us,5.14us,243.82us,282.60us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,367,651.79ms,1.36ms,5.17us,1.36ms,12.36us,1.34ms,1.47ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,301.06ms,241.70us,2.26us,242.32us,11.77us,238.28us,592.96us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,970,601.94ms,513.45us,3.66us,515.23us,8.52us,502.44us,656.45us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.84ms,480.20us,5.03us,481.06us,9.70us,466.10us,633.78us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.81ms,486.09us,1.97us,488.03us,13.90us,478.34us,782.52us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.72ms,82.12us,535.00ns,83.08us,3.61us,79.10us,122.57us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.78ms,44.44us,214.00ns,44.86us,1.60us,43.69us,63.55us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.76ms,63.65us,57.00ns,64.34us,1.93us,63.43us,79.38us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.66ms,57.31us,171.00ns,58.30us,3.29us,56.65us,86.80us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,100.69ms,44.82us,76.00ns,45.29us,1.69us,44.44us,64.49us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.74ms,80.79us,138.00ns,81.50us,1.74us,80.47us,95.85us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,300.96ms,230.60us,2.69us,231.19us,4.82us,225.15us,268.42us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.50ms,50.70us,1.06us,51.47us,2.35us,49.16us,78.80us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.57ms,90.17us,1.38us,90.62us,2.88us,87.19us,120.22us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,201.56ms,134.23us,185.00ns,135.42us,2.66us,133.57us,165.43us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,251.72ms,134.89us,1.48us,137.25us,5.53us,131.79us,184.33us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,401.19ms,330.27us,3.04us,330.63us,5.75us,321.56us,368.88us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,201.61ms,155.21us,1.49us,156.72us,3.81us,152.73us,188.27us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.98ms,290.14us,3.64us,290.05us,5.85us,284.48us,365.90us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,602.13ms,465.49us,4.68us,467.63us,9.64us,448.06us,590.25us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.58ms,99.27us,1.68us,99.80us,2.87us,96.50us,125.29us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,253,751.62ms,1.98ms,7.25us,1.98ms,10.37us,1.96ms,2.02ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.54ms,442.06us,2.74us,442.80us,7.69us,433.58us,628.38us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,962,802.22ms,518.25us,4.42us,519.36us,7.45us,504.29us,564.11us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,847,601.85ms,589.33us,3.54us,590.32us,7.12us,577.16us,630.43us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.18ms,9.32ms,19.34us,9.33ms,46.88us,9.26ms,9.49ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,336,701.78ms,1.49ms,11.01us,1.49ms,16.37us,1.46ms,1.61ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.58ms,85.24us,1.10us,87.18us,19.81us,81.50us,683.10us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.44ms,24.01us,80.00ns,24.26us,1.32us,23.73us,40.11us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.48ms,63.74us,45.00ns,64.28us,1.71us,63.46us,87.66us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.55ms,84.26us,643.00ns,84.91us,2.47us,81.29us,115.88us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.42ms,23.82us,62.00ns,24.13us,1.60us,23.56us,47.24us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,101.32ms,63.78us,45.00ns,64.32us,1.69us,63.55us,88.77us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.49ms,29.07us,115.00ns,29.40us,1.60us,28.68us,50.09us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.49ms,81.52us,84.00ns,82.25us,2.04us,81.32us,106.65us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.46ms,80.48us,76.00ns,81.12us,1.66us,80.20us,99.44us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.46ms,29.17us,65.00ns,29.49us,1.36us,28.96us,46.45us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.49ms,83.02us,1.40us,82.95us,2.07us,81.33us,105.40us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.47ms,80.66us,57.00ns,81.37us,2.20us,80.46us,118.72us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,598,852.38ms,828.23us,8.87us,835.84us,21.70us,803.86us,1.05ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,681,601.56ms,733.91us,4.17us,734.67us,7.34us,723.52us,778.78us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,426,652.20ms,1.17ms,7.99us,1.18ms,16.15us,1.15ms,1.26ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,282,701.71ms,1.77ms,8.35us,1.78ms,15.38us,1.76ms,1.83ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,122,1.60s,4.12ms,48.38us,4.12ms,58.24us,4.01ms,4.25ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,292,701.87ms,1.70ms,6.64us,1.71ms,40.05us,1.69ms,2.15ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,751.87ms,51.94ms,291.55us,51.65ms,582.57us,50.94ms,52.29ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,752.20ms,21.21ms,37.85us,21.20ms,54.13us,21.12ms,21.32ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.54ms,104.70us,789.00ns,105.63us,2.67us,102.36us,127.45us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.47ms,68.15us,1.44us,68.44us,2.27us,65.80us,92.10us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.50ms,72.98us,65.00ns,73.64us,2.00us,72.76us,100.31us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,101.09ms,46.97us,162.00ns,47.55us,2.04us,46.53us,68.03us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.47ms,83.11us,1.72us,83.89us,2.91us,79.80us,101.35us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.54ms,107.04us,220.00ns,107.94us,2.23us,106.56us,134.47us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.55ms,111.73us,820.00ns,112.65us,2.76us,108.78us,139.93us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.50ms,44.44us,301.00ns,44.90us,1.84us,43.45us,69.55us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.52ms,74.39us,61.00ns,75.04us,1.83us,74.16us,98.27us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.27ms,344.20us,3.94us,345.57us,6.12us,333.57us,369.69us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,198,752.17ms,2.53ms,13.32us,2.53ms,17.77us,2.49ms,2.58ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.78ms,491.71us,2.91us,491.85us,5.01us,481.45us,546.14us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,301.71ms,215.50us,1.63us,216.40us,3.19us,210.79us,234.85us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,369,652.01ms,1.35ms,4.02us,1.36ms,8.10us,1.34ms,1.42ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.82ms,241.30us,1.37us,242.60us,3.19us,239.68us,272.50us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.07ms,371.35us,3.18us,371.75us,5.59us,358.15us,405.75us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.87ms,475.80us,4.52us,476.20us,6.57us,460.57us,513.35us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.73ms,483.58us,2.25us,483.82us,3.97us,475.47us,523.60us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.55ms,84.15us,587.00ns,84.83us,2.36us,81.06us,105.18us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.49ms,44.49us,217.00ns,44.87us,1.63us,43.59us,70.20us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,63.80us,45.00ns,64.34us,1.76us,63.62us,92.47us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.52ms,28.88us,59.00ns,29.21us,1.54us,28.68us,48.39us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,101.35ms,44.84us,81.00ns,45.29us,1.67us,44.53us,69.98us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.50ms,80.40us,54.00ns,81.09us,1.92us,80.20us,107.16us diff --git a/audit/rebar/results/ice/rebar-audit-pass2.csv b/audit/rebar/results/ice/rebar-audit-pass2.csv index 92b99ee..864a359 100644 --- a/audit/rebar/results/ice/rebar-audit-pass2.csv +++ b/audit/rebar/results/ice/rebar-audit-pass2.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,351.29ms,272.87us,2.88us,273.35us,5.52us,259.99us,312.32us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.64ms,35.95us,393.00ns,36.69us,2.86us,35.33us,73.97us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.86ms,92.69us,1.41us,93.50us,3.75us,89.41us,115.92us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,201.02ms,135.46us,188.00ns,137.16us,3.75us,134.97us,164.52us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,501.58ms,412.56us,2.52us,413.00us,6.96us,400.97us,520.86us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.49ms,381.68us,2.48us,381.74us,6.91us,373.04us,482.55us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.87ms,154.72us,810.00ns,157.20us,4.49us,153.20us,179.73us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.28ms,290.77us,3.07us,289.75us,4.79us,283.81us,326.78us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,885,601.64ms,562.66us,3.75us,564.45us,10.68us,546.96us,709.44us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.73ms,80.17us,123.00ns,80.98us,1.97us,79.85us,95.40us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,252,702.16ms,1.98ms,8.57us,1.99ms,21.71us,1.97ms,2.14ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.77ms,441.84us,3.43us,442.92us,5.31us,435.03us,472.11us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,72,752.19ms,7.00ms,19.67us,7.01ms,53.62us,6.96ms,7.32ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,719,601.90ms,693.84us,3.86us,695.95us,14.24us,681.86us,933.31us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,53,752.30ms,9.49ms,23.23us,9.48ms,26.10us,9.43ms,9.54ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,332,702.23ms,1.51ms,9.61us,1.51ms,12.62us,1.48ms,1.55ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.76ms,81.99us,531.00ns,83.05us,3.61us,78.90us,122.80us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.58ms,16.55us,28.00ns,16.92us,2.30us,16.44us,53.15us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.73ms,63.68us,107.00ns,65.27us,6.05us,63.47us,201.62us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.68ms,82.36us,547.00ns,83.30us,2.80us,79.32us,109.00us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.67ms,16.52us,30.00ns,16.97us,2.46us,16.41us,52.77us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.69ms,63.78us,54.00ns,64.50us,2.21us,63.57us,86.09us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.67ms,57.84us,168.00ns,58.45us,2.01us,57.13us,82.25us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.90ms,86.53us,193.00ns,87.48us,2.31us,86.20us,115.48us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.73ms,80.55us,77.00ns,81.37us,2.23us,80.27us,103.80us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.70ms,56.71us,136.00ns,57.39us,2.21us,56.07us,77.20us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.86ms,86.52us,205.00ns,87.35us,2.14us,86.11us,111.31us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.68ms,80.65us,62.00ns,81.33us,1.65us,80.45us,92.65us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,504,701.66ms,0.98ms,37.32us,0.99ms,61.93us,894.56us,1.53ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,684,651.88ms,726.01us,19.74us,731.52us,31.10us,669.44us,921.34us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,344,701.92ms,1.44ms,52.50us,1.46ms,86.04us,1.22ms,1.78ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,217,752.01ms,2.30ms,43.48us,2.31ms,84.56us,2.16ms,2.91ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,109,751.81ms,4.59ms,38.65us,4.59ms,58.34us,4.46ms,4.78ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,294,752.10ms,1.70ms,53.97us,1.71ms,89.28us,1.50ms,2.01ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,752.05ms,51.08ms,70.90us,51.09ms,92.65us,50.98ms,51.30ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,752.16ms,21.35ms,14.94us,21.36ms,22.86us,21.32ms,21.41ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.83ms,106.66us,1.34us,107.82us,3.37us,102.65us,125.48us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.73ms,67.83us,1.27us,68.46us,2.84us,65.48us,96.46us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.74ms,72.86us,64.00ns,73.74us,2.20us,72.58us,94.93us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.69ms,66.41us,323.00ns,67.39us,2.77us,65.55us,105.91us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.74ms,83.95us,2.17us,84.52us,3.32us,80.10us,105.25us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.82ms,107.32us,139.00ns,108.59us,2.98us,106.73us,140.50us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.88ms,116.98us,830.00ns,118.14us,2.95us,114.27us,146.41us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.73ms,44.39us,287.00ns,44.88us,1.89us,43.29us,65.18us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.76ms,74.67us,56.00ns,75.42us,1.93us,74.49us,92.56us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.48ms,383.72us,3.08us,384.72us,9.35us,370.08us,545.42us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,198,752.24ms,2.52ms,11.01us,2.53ms,26.52us,2.50ms,2.69ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.82ms,489.89us,1.36us,491.13us,3.94us,484.13us,515.56us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,301.11ms,252.09us,2.42us,253.59us,6.41us,243.94us,293.22us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,360,651.89ms,1.36ms,8.17us,1.39ms,54.95us,1.34ms,1.55ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,301.21ms,239.76us,1.95us,239.94us,3.08us,236.58us,275.08us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,969,601.91ms,516.12us,5.86us,516.06us,7.87us,501.23us,568.91us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.89ms,476.68us,4.97us,477.51us,8.51us,460.74us,585.79us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.91ms,485.49us,2.76us,488.16us,10.93us,475.23us,639.56us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.73ms,82.39us,718.00ns,84.96us,9.80us,79.56us,269.93us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.81ms,44.60us,378.00ns,45.36us,2.32us,43.82us,75.42us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.86ms,63.73us,82.00ns,64.81us,2.33us,63.47us,85.59us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.87ms,56.93us,234.00ns,57.88us,2.81us,56.14us,85.38us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,100.87ms,44.95us,295.00ns,46.53us,4.13us,44.49us,110.20us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.89ms,80.59us,68.00ns,81.46us,2.37us,80.35us,113.22us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,301.31ms,230.38us,2.60us,230.58us,4.27us,225.31us,268.40us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.53ms,51.44us,1.42us,52.12us,2.72us,49.37us,81.93us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.59ms,91.22us,1.64us,91.78us,3.07us,87.38us,120.02us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,201.48ms,135.38us,162.00ns,136.65us,2.70us,134.89us,164.15us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,250.82ms,135.34us,835.00ns,137.61us,4.76us,133.26us,173.88us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,401.09ms,332.82us,5.14us,333.41us,6.75us,323.22us,379.60us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.71ms,154.20us,611.00ns,156.56us,4.42us,152.58us,200.90us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.08ms,290.15us,4.50us,290.04us,5.76us,283.91us,333.00us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,601.74ms,467.16us,6.62us,470.46us,18.54us,447.16us,663.95us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.86ms,99.02us,1.74us,99.80us,3.57us,95.86us,132.04us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,254,751.52ms,1.97ms,4.26us,1.97ms,9.11us,1.96ms,2.02ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.77ms,447.73us,2.92us,448.10us,4.93us,439.19us,477.00us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,958,802.29ms,519.81us,5.62us,521.29us,9.88us,505.08us,601.01us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,846,601.58ms,591.11us,4.11us,591.50us,7.08us,578.00us,634.69us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.90ms,9.32ms,25.34us,9.34ms,68.74us,9.25ms,9.51ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,335,702.13ms,1.49ms,9.85us,1.49ms,13.72us,1.46ms,1.55ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.56ms,84.32us,586.00ns,85.18us,2.65us,81.36us,107.33us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.44ms,23.66us,62.00ns,23.93us,1.48us,23.39us,43.29us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,63.74us,47.00ns,64.42us,3.00us,63.54us,137.20us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,151.44ms,84.21us,682.00ns,85.08us,3.07us,82.03us,120.18us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.43ms,23.89us,74.00ns,24.14us,1.24us,23.68us,45.37us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,63.84us,43.00ns,64.40us,1.80us,63.63us,87.75us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.49ms,29.07us,40.00ns,29.37us,1.33us,28.91us,47.52us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.46ms,83.33us,88.00ns,84.06us,2.14us,83.02us,110.33us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.46ms,80.34us,63.00ns,81.04us,2.03us,80.13us,108.34us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.48ms,29.05us,46.00ns,29.35us,1.36us,28.88us,45.45us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.49ms,83.21us,118.00ns,84.00us,2.04us,82.89us,103.34us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.47ms,80.39us,80.00ns,81.07us,2.09us,80.15us,120.80us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,585,852.13ms,851.66us,4.23us,854.75us,10.48us,837.60us,912.77us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,651,601.58ms,768.19us,4.10us,768.36us,7.23us,756.78us,804.98us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,427,652.11ms,1.17ms,5.46us,1.17ms,10.37us,1.16ms,1.23ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,283,701.78ms,1.77ms,5.79us,1.77ms,11.76us,1.75ms,1.81ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,124,1.55s,4.05ms,20.36us,4.05ms,38.95us,4.00ms,4.23ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,293,701.75ms,1.71ms,6.12us,1.71ms,14.58us,1.69ms,1.78ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,752.17ms,51.09ms,70.31us,51.08ms,77.73us,50.97ms,51.18ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,751.82ms,21.05ms,45.88us,21.16ms,274.37us,20.97ms,21.88ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,151.35ms,104.25us,898.00ns,105.06us,2.52us,102.76us,127.65us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.47ms,66.60us,851.00ns,67.34us,2.00us,65.17us,86.61us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,101.30ms,72.57us,66.00ns,73.12us,1.45us,72.37us,87.21us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.44ms,47.14us,205.00ns,47.62us,1.82us,46.59us,73.31us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.46ms,83.04us,1.84us,83.77us,3.08us,79.93us,114.71us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.55ms,107.14us,233.00ns,107.92us,1.89us,106.65us,133.55us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.52ms,111.72us,780.00ns,112.67us,2.57us,109.41us,140.66us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.51ms,44.63us,303.00ns,45.09us,2.01us,43.61us,71.22us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.49ms,74.49us,63.00ns,75.13us,1.83us,74.23us,100.06us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.77ms,343.98us,3.92us,345.38us,6.42us,333.35us,394.44us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,199,751.96ms,2.51ms,7.55us,2.51ms,11.67us,2.49ms,2.56ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.84ms,493.52us,2.94us,493.63us,5.04us,483.49us,542.53us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,301.65ms,215.56us,1.50us,216.65us,3.52us,210.75us,249.06us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,350,651.25ms,1.42ms,56.46us,1.43ms,50.69us,1.34ms,1.56ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,301.57ms,240.69us,1.80us,240.82us,2.40us,238.03us,258.91us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.09ms,369.39us,2.63us,369.56us,4.51us,354.33us,395.85us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.91ms,474.44us,4.47us,474.86us,6.52us,458.52us,523.16us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.84ms,481.89us,2.23us,482.23us,3.87us,474.34us,520.73us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.58ms,84.16us,536.00ns,84.93us,2.49us,81.00us,108.11us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.52ms,44.37us,211.00ns,44.80us,1.65us,43.44us,69.47us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,101.34ms,63.80us,47.00ns,64.32us,1.59us,63.57us,85.90us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.47ms,28.90us,41.00ns,29.18us,1.28us,28.71us,47.34us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,100.51ms,44.88us,81.00ns,45.28us,1.52us,44.57us,66.73us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.48ms,80.17us,65.00ns,80.81us,1.73us,79.97us,108.45us diff --git a/audit/rebar/results/ice/rebar-audit-pass3.csv b/audit/rebar/results/ice/rebar-audit-pass3.csv index 2a059bf..f1818b3 100644 --- a/audit/rebar/results/ice/rebar-audit-pass3.csv +++ b/audit/rebar/results/ice/rebar-audit-pass3.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,351.41ms,270.65us,3.54us,272.65us,8.22us,258.84us,383.79us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.70ms,35.75us,211.00ns,36.32us,1.86us,35.27us,59.10us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.97ms,90.70us,1.68us,91.24us,3.12us,87.01us,110.43us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,201.03ms,134.08us,341.00ns,135.74us,3.24us,133.43us,156.69us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,451.47ms,401.75us,4.07us,402.95us,9.69us,387.88us,501.96us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.60ms,381.92us,2.39us,383.06us,10.59us,373.46us,624.03us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.97ms,156.19us,1.20us,158.42us,4.28us,153.86us,183.71us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.36ms,292.97us,3.90us,295.06us,34.53us,284.91us,928.44us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,879,601.82ms,568.92us,9.06us,568.25us,12.04us,538.96us,603.81us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.77ms,79.80us,154.00ns,80.84us,2.93us,79.19us,115.25us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,252,702.28ms,1.98ms,7.53us,1.99ms,18.23us,1.97ms,2.13ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.88ms,442.99us,1.80us,444.85us,8.44us,436.51us,556.30us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,73,752.15ms,6.86ms,30.24us,6.91ms,121.86us,6.79ms,7.43ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,716,602.18ms,695.60us,6.27us,698.92us,18.16us,681.01us,0.96ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.43ms,9.44ms,43.39us,9.43ms,85.57us,9.30ms,9.76ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,337,702.32ms,1.48ms,9.41us,1.48ms,16.50us,1.46ms,1.63ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.77ms,82.33us,0.99us,83.24us,3.41us,79.05us,111.95us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.66ms,16.53us,29.00ns,16.86us,2.25us,16.42us,59.39us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.79ms,63.72us,58.00ns,64.53us,2.45us,63.50us,83.47us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.71ms,82.08us,448.00ns,83.21us,3.75us,79.26us,117.84us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.67ms,16.54us,57.00ns,16.96us,1.95us,16.42us,55.43us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.77ms,63.77us,54.00ns,64.48us,2.28us,63.55us,93.39us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.73ms,57.12us,174.00ns,57.89us,2.61us,56.37us,87.57us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.97ms,88.06us,189.00ns,89.15us,2.81us,87.76us,118.53us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.73ms,80.44us,71.00ns,81.26us,2.22us,80.20us,107.71us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.74ms,57.57us,179.00ns,58.57us,3.14us,56.82us,92.71us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.92ms,86.59us,267.00ns,87.68us,2.47us,86.22us,110.73us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.80ms,80.36us,71.00ns,81.19us,1.99us,80.11us,94.72us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,438,702.17ms,1.13ms,54.98us,1.14ms,84.76us,0.96ms,1.40ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,661,652.04ms,752.37us,29.14us,756.83us,42.40us,673.47us,0.98ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,306,702.22ms,1.61ms,89.45us,1.63ms,161.37us,1.36ms,2.65ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,207,752.33ms,2.39ms,68.96us,2.42ms,119.63us,2.17ms,2.83ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,108,752.07ms,4.64ms,47.92us,4.65ms,73.29us,4.49ms,4.91ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,259,752.37ms,1.93ms,85.39us,1.94ms,121.09us,1.69ms,2.32ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,752.30ms,51.27ms,140.15us,51.43ms,391.38us,51.07ms,52.39ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,802.47ms,21.38ms,29.12us,21.40ms,72.77us,21.32ms,21.63ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.98ms,106.86us,1.06us,108.04us,4.37us,103.33us,159.96us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.78ms,68.29us,1.70us,68.97us,3.19us,65.47us,99.41us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.80ms,72.78us,96.00ns,73.99us,2.68us,72.54us,97.70us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.72ms,66.44us,352.00ns,67.92us,5.43us,65.64us,181.28us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.88ms,83.95us,2.20us,84.57us,3.31us,80.18us,103.18us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.90ms,107.25us,139.00ns,108.30us,2.31us,106.68us,130.40us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.81ms,116.84us,1.09us,118.64us,6.74us,113.88us,240.37us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.82ms,44.60us,314.00ns,46.21us,5.96us,43.72us,159.05us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.80ms,74.25us,62.00ns,75.12us,2.19us,74.06us,97.05us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.57ms,383.22us,3.41us,383.75us,6.35us,369.55us,471.80us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,199,752.42ms,2.52ms,9.27us,2.52ms,16.56us,2.50ms,2.62ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.91ms,491.73us,4.53us,491.86us,6.34us,482.86us,548.69us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,301.29ms,248.15us,4.48us,248.27us,7.00us,232.61us,282.32us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,364,652.12ms,1.37ms,7.28us,1.37ms,19.95us,1.35ms,1.45ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,301.30ms,240.14us,783.00ns,242.57us,7.45us,238.89us,401.56us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,965,602.04ms,516.38us,4.60us,518.18us,10.03us,502.00us,635.03us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.88ms,479.54us,5.72us,479.90us,8.53us,460.87us,583.36us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.86ms,485.11us,2.10us,485.63us,4.22us,474.59us,521.96us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.78ms,82.43us,1.07us,83.35us,3.18us,79.08us,124.11us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.73ms,44.26us,199.00ns,44.85us,2.42us,43.35us,76.15us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.78ms,63.72us,58.00ns,64.38us,1.89us,63.53us,83.48us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.73ms,56.66us,308.00ns,58.25us,5.15us,55.85us,149.34us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,100.82ms,44.83us,84.00ns,45.35us,1.89us,44.50us,68.20us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.81ms,80.22us,58.00ns,80.98us,2.02us,80.01us,101.75us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,301.29ms,229.75us,2.60us,230.02us,4.15us,224.93us,265.25us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.50ms,51.31us,424.00ns,51.85us,1.98us,49.92us,80.06us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,150.58ms,90.40us,1.41us,90.67us,2.70us,86.95us,121.63us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.63ms,134.12us,240.00ns,135.30us,2.39us,133.44us,158.66us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,251.26ms,136.18us,1.31us,138.08us,4.67us,133.38us,179.85us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,401.09ms,332.04us,4.33us,332.14us,6.14us,323.30us,364.49us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,201.62ms,156.35us,1.04us,158.38us,3.92us,154.52us,191.46us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.11ms,289.54us,4.99us,289.47us,7.69us,282.82us,438.75us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,602.11ms,465.86us,5.08us,467.63us,9.20us,447.13us,553.14us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.60ms,99.52us,1.86us,99.96us,3.21us,95.95us,138.93us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,252,751.52ms,1.99ms,5.54us,1.99ms,11.70us,1.97ms,2.08ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,501.63ms,442.01us,1.96us,442.63us,6.05us,434.39us,542.58us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,962,802.14ms,518.09us,2.74us,519.23us,6.40us,505.24us,550.78us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,837,601.76ms,594.00us,3.92us,597.87us,15.46us,582.55us,846.85us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.27ms,9.31ms,26.35us,9.35ms,73.45us,9.27ms,9.56ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,335,701.65ms,1.49ms,10.35us,1.49ms,13.51us,1.47ms,1.55ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,151.43ms,84.20us,589.00ns,84.98us,2.60us,81.23us,107.54us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.42ms,23.91us,73.00ns,24.18us,1.43us,23.67us,45.51us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,63.79us,49.00ns,64.38us,1.88us,63.54us,86.10us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.62ms,84.72us,1.03us,86.39us,6.17us,81.45us,202.51us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.45ms,24.02us,81.00ns,24.26us,1.28us,23.70us,42.72us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.52ms,63.84us,46.00ns,64.44us,1.93us,63.62us,90.88us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.50ms,29.04us,94.00ns,29.42us,1.72us,28.81us,53.12us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.50ms,81.62us,90.00ns,82.34us,2.00us,81.40us,109.45us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.48ms,80.35us,82.00ns,81.01us,1.77us,80.11us,99.95us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.48ms,29.10us,118.00ns,29.43us,1.51us,28.83us,45.05us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.48ms,81.66us,96.00ns,82.42us,2.24us,81.40us,113.68us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.48ms,81.06us,856.00ns,85.41us,27.13us,79.93us,331.75us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,596,854.32ms,832.64us,9.67us,839.13us,23.62us,809.49us,1.05ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,648,601.50ms,770.33us,4.78us,771.70us,9.68us,757.72us,833.53us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,427,652.13ms,1.17ms,6.76us,1.17ms,14.89us,1.15ms,1.25ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,283,701.79ms,1.77ms,6.21us,1.77ms,13.91us,1.75ms,1.83ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,124,1.60s,4.04ms,24.21us,4.05ms,52.36us,3.98ms,4.42ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,290,702.25ms,1.72ms,9.30us,1.73ms,69.53us,1.69ms,2.75ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,10,751.84ms,51.07ms,25.82us,51.08ms,47.81us,51.03ms,51.20ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,24,752.19ms,21.32ms,193.11us,21.54ms,365.82us,21.09ms,21.98ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.49ms,105.42us,1.05us,106.61us,6.22us,103.02us,275.61us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.48ms,68.87us,1.60us,69.33us,2.55us,66.10us,93.69us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.48ms,73.03us,478.00ns,74.00us,3.53us,72.37us,157.11us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.50ms,46.88us,162.00ns,47.51us,2.43us,46.43us,74.19us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.47ms,83.28us,1.93us,83.92us,2.98us,79.85us,102.89us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.55ms,108.94us,171.00ns,109.78us,1.89us,108.51us,127.64us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.54ms,111.48us,938.00ns,112.27us,2.60us,109.86us,142.49us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.49ms,44.80us,220.00ns,45.21us,1.74us,43.90us,70.99us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.51ms,74.56us,59.00ns,75.17us,1.72us,74.34us,100.03us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.11ms,341.56us,3.18us,343.23us,6.48us,331.67us,371.88us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,199,752.19ms,2.51ms,8.06us,2.52ms,17.27us,2.49ms,2.64ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.90ms,495.39us,2.60us,497.21us,21.96us,486.15us,938.75us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,301.57ms,215.16us,1.60us,216.23us,3.08us,210.14us,238.04us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,351,652.05ms,1.47ms,31.88us,1.42ms,67.04us,1.34ms,1.52ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,301.65ms,251.53us,1.71us,251.80us,2.61us,249.03us,278.50us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.03ms,369.85us,2.56us,370.24us,5.01us,355.53us,411.16us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.98ms,480.69us,4.76us,481.08us,7.00us,458.00us,524.55us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,551.12ms,485.11us,2.50us,485.14us,4.11us,473.96us,535.65us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.57ms,84.17us,690.00ns,84.80us,2.29us,82.13us,113.31us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,100.52ms,44.40us,214.00ns,44.76us,1.47us,43.26us,65.48us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.49ms,63.79us,47.00ns,64.35us,1.74us,63.53us,85.38us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.49ms,29.11us,61.00ns,29.39us,1.36us,28.83us,44.10us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,100.48ms,44.91us,98.00ns,45.28us,1.45us,44.51us,62.40us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,101.33ms,80.21us,52.00ns,80.83us,1.60us,80.00us,101.78us diff --git a/audit/rebar/results/spr/rebar-audit-pass1.csv b/audit/rebar/results/spr/rebar-audit-pass1.csv index 04553c9..145184a 100644 --- a/audit/rebar/results/spr/rebar-audit-pass1.csv +++ b/audit/rebar/results/spr/rebar-audit-pass1.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,300.90ms,249.51us,3.18us,249.46us,4.89us,241.52us,308.46us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.46ms,28.71us,79.00ns,29.39us,1.71us,28.48us,48.54us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.51ms,81.80us,1.48us,82.14us,3.23us,77.84us,134.79us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.77ms,137.64us,100.00ns,138.88us,2.29us,137.38us,150.56us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,401.01ms,325.61us,3.88us,326.49us,8.87us,315.99us,522.67us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.20ms,364.62us,2.65us,364.34us,5.21us,354.90us,426.04us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.77ms,132.21us,369.00ns,133.62us,2.80us,131.17us,159.42us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.02ms,300.33us,2.70us,300.09us,3.43us,296.15us,334.27us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,954,601.27ms,523.48us,2.86us,524.08us,4.58us,514.54us,548.46us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.57ms,74.60us,174.00ns,75.44us,2.09us,73.97us,89.85us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.66ms,2.27ms,9.21us,2.28ms,16.67us,2.25ms,2.36ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,551.32ms,482.36us,1.89us,482.32us,3.36us,474.16us,511.16us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,79,751.58ms,6.34ms,16.25us,6.34ms,20.70us,6.31ms,6.40ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,725,601.49ms,690.42us,4.44us,690.32us,8.15us,673.35us,730.61us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.52ms,9.40ms,22.82us,9.40ms,38.19us,9.34ms,9.50ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,305,701.54ms,1.64ms,9.50us,1.64ms,13.66us,1.62ms,1.69ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.52ms,83.93us,1.14us,85.30us,3.68us,81.02us,107.85us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.42ms,13.13us,23.00ns,13.30us,1.14us,13.04us,26.39us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.52ms,66.18us,46.00ns,66.85us,1.80us,66.03us,79.42us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.50ms,84.30us,1.29us,85.91us,3.96us,81.20us,111.89us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.48ms,13.18us,23.00ns,13.44us,1.64us,13.09us,38.28us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.57ms,66.27us,43.00ns,66.90us,1.71us,66.07us,80.07us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.54ms,48.57us,336.00ns,49.72us,4.26us,47.89us,150.32us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.65ms,94.75us,777.00ns,95.62us,2.54us,93.05us,115.13us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.55ms,83.34us,120.00ns,84.16us,2.05us,83.05us,104.38us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.53ms,46.51us,317.00ns,47.32us,2.51us,45.75us,69.91us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.70ms,93.33us,434.00ns,94.61us,3.07us,92.44us,121.72us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.57ms,83.32us,81.00ns,84.12us,2.07us,83.03us,114.19us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,651,651.35ms,768.72us,5.60us,767.89us,11.54us,747.52us,910.89us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,766,601.35ms,651.26us,3.91us,653.17us,6.02us,645.06us,684.64us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,525,651.33ms,0.95ms,1.42us,0.95ms,4.95us,939.80us,0.99ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,276,751.60ms,1.82ms,2.88us,1.82ms,6.61us,1.81ms,1.85ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,122,751.87ms,4.10ms,26.43us,4.10ms,39.67us,4.03ms,4.20ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,379,701.38ms,1.32ms,6.47us,1.32ms,9.05us,1.30ms,1.35ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,751.45ms,55.67ms,196.30us,55.79ms,251.50us,55.47ms,56.24ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,751.54ms,20.45ms,30.15us,20.46ms,45.03us,20.38ms,20.56ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.62ms,105.11us,1.21us,106.28us,2.84us,102.53us,128.34us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.55ms,57.63us,799.00ns,58.51us,2.14us,56.31us,72.83us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.57ms,75.43us,59.00ns,76.17us,1.88us,75.23us,91.51us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.57ms,57.06us,356.00ns,57.95us,2.54us,56.22us,76.29us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.54ms,75.27us,1.92us,76.18us,3.06us,72.17us,102.23us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.59ms,111.64us,144.00ns,112.67us,2.11us,111.23us,125.91us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.57ms,114.06us,1.27us,115.48us,3.37us,111.68us,136.14us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.43ms,37.57us,307.00ns,38.00us,1.43us,37.10us,51.77us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.49ms,77.02us,58.00ns,77.85us,2.19us,76.80us,97.84us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.03ms,367.60us,4.53us,368.47us,5.65us,359.75us,402.29us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,182,751.60ms,2.76ms,6.96us,2.76ms,10.93us,2.73ms,2.80ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,935,601.39ms,534.29us,2.53us,534.67us,4.55us,526.15us,597.05us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.88ms,229.16us,3.43us,230.23us,4.86us,223.26us,252.22us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,336,651.48ms,1.48ms,9.32us,1.49ms,20.23us,1.46ms,1.61ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.91ms,242.14us,1.59us,243.46us,2.78us,239.96us,270.20us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,501.22ms,421.04us,4.19us,421.25us,5.32us,411.59us,451.45us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.31ms,466.87us,4.17us,466.77us,5.91us,452.16us,504.08us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,964,601.47ms,518.06us,2.04us,518.64us,3.83us,508.98us,539.31us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.55ms,84.16us,1.19us,86.31us,4.77us,81.34us,106.92us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.43ms,37.68us,224.00ns,38.13us,1.79us,37.11us,57.85us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,66.31us,41.00ns,66.99us,1.90us,66.09us,83.70us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.52ms,45.98us,109.00ns,46.78us,2.79us,45.60us,78.98us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.48ms,36.19us,124.00ns,36.57us,1.44us,35.80us,50.58us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.52ms,83.52us,100.00ns,84.31us,1.89us,83.20us,94.50us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,301.60ms,224.90us,3.10us,225.94us,4.78us,217.60us,262.00us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.45ms,45.60us,125.00ns,46.06us,1.72us,45.26us,66.77us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.43ms,82.11us,1.54us,82.51us,3.71us,78.32us,159.32us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.54ms,137.48us,121.00ns,138.80us,2.63us,137.10us,166.15us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,200.57ms,121.23us,1.15us,122.63us,3.51us,118.62us,157.68us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,401.59ms,331.85us,4.30us,333.24us,7.73us,320.06us,394.87us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.56ms,135.59us,2.48us,135.65us,3.83us,131.66us,175.40us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.76ms,301.18us,2.08us,300.60us,3.96us,296.29us,340.88us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,601.32ms,457.61us,3.66us,458.09us,6.22us,441.59us,488.69us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.50ms,93.14us,1.94us,94.33us,3.70us,90.26us,129.78us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.44ms,2.27ms,5.85us,2.28ms,12.88us,2.26ms,2.35ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,550.92ms,484.11us,3.48us,484.67us,5.45us,473.76us,510.56us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,951,751.99ms,528.00us,4.65us,525.60us,14.00us,479.15us,600.82us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,802,601.03ms,622.70us,3.25us,623.94us,6.56us,610.40us,658.74us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.33ms,9.37ms,19.63us,9.38ms,27.89us,9.34ms,9.45ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,304,701.21ms,1.65ms,12.62us,1.65ms,17.84us,1.62ms,1.73ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.49ms,88.12us,2.17us,88.73us,4.33us,82.87us,116.78us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.38ms,20.39us,74.00ns,20.65us,1.48us,20.17us,47.62us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.41ms,66.17us,44.00ns,66.80us,1.78us,65.99us,86.75us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.51ms,88.08us,1.60us,88.72us,4.26us,82.99us,118.78us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.35ms,19.84us,45.00ns,20.05us,1.12us,19.64us,33.82us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.39ms,66.28us,54.00ns,66.90us,1.77us,66.12us,87.51us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.33ms,24.44us,180.00ns,24.79us,1.82us,24.01us,39.90us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.43ms,83.44us,130.00ns,84.44us,2.76us,83.14us,124.57us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.39ms,83.51us,267.00ns,84.22us,2.39us,82.98us,124.75us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.35ms,23.81us,89.00ns,24.25us,1.89us,23.53us,41.99us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.42ms,83.40us,63.00ns,84.39us,2.94us,83.21us,134.71us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.46ms,83.45us,124.00ns,84.30us,2.10us,83.15us,104.70us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,698,802.39ms,714.22us,5.50us,716.04us,9.21us,704.79us,763.32us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,757,601.18ms,657.95us,3.02us,660.49us,7.19us,647.10us,707.61us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,546,652.23ms,914.25us,2.02us,915.71us,8.04us,900.92us,0.96ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,276,752.31ms,1.82ms,1.83us,1.82ms,7.26us,1.81ms,1.85ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,127,1.55s,3.97ms,35.36us,3.96ms,53.57us,3.82ms,4.07ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,267,752.33ms,1.87ms,2.77us,1.88ms,9.00us,1.86ms,1.92ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,751.28ms,55.80ms,173.53us,55.81ms,242.38us,55.42ms,56.17ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,752.04ms,20.50ms,43.24us,20.51ms,71.21us,20.41ms,20.65ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.45ms,106.44us,0.97us,107.19us,3.29us,101.73us,127.77us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.43ms,58.00us,849.00ns,59.02us,2.79us,56.31us,104.48us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,101.32ms,75.48us,51.00ns,76.21us,2.00us,75.30us,98.19us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.42ms,41.33us,241.00ns,42.05us,2.58us,40.69us,66.12us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.41ms,75.71us,2.16us,76.45us,3.32us,72.18us,95.33us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.50ms,111.70us,127.00ns,112.75us,2.35us,111.35us,134.26us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,151.38ms,113.06us,2.14us,113.55us,3.38us,109.03us,139.35us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.35ms,37.62us,147.00ns,38.11us,1.56us,37.16us,53.82us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.41ms,77.11us,65.00ns,77.86us,2.05us,76.88us,100.93us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,450.97ms,341.03us,2.82us,341.35us,5.72us,331.75us,403.81us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,182,751.17ms,2.76ms,7.17us,2.76ms,11.91us,2.73ms,2.80ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,929,601.00ms,537.85us,3.18us,538.20us,5.14us,527.14us,571.18us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.62ms,206.15us,2.44us,206.67us,4.01us,199.53us,235.83us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,338,651.96ms,1.48ms,8.46us,1.48ms,19.71us,1.46ms,1.57ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.68ms,243.73us,2.17us,243.60us,2.84us,240.26us,260.00us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,350.71ms,308.06us,3.61us,308.06us,5.34us,293.22us,327.35us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,550.98ms,466.40us,4.59us,466.63us,6.87us,452.80us,539.57us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,967,601.06ms,516.38us,2.56us,517.18us,4.63us,505.86us,556.26us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.49ms,88.22us,1.71us,89.38us,4.88us,82.64us,110.76us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.35ms,37.66us,171.00ns,38.05us,1.36us,37.26us,50.87us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.40ms,66.30us,46.00ns,66.91us,1.81us,66.13us,84.88us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.34ms,24.82us,57.00ns,25.24us,1.75us,24.51us,42.98us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.32ms,36.07us,83.00ns,36.53us,1.94us,35.81us,61.68us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.37ms,83.42us,70.00ns,84.21us,2.08us,83.14us,102.96us diff --git a/audit/rebar/results/spr/rebar-audit-pass2.csv b/audit/rebar/results/spr/rebar-audit-pass2.csv index 3450e72..0b15051 100644 --- a/audit/rebar/results/spr/rebar-audit-pass2.csv +++ b/audit/rebar/results/spr/rebar-audit-pass2.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,300.84ms,250.14us,3.08us,250.44us,4.58us,242.16us,275.78us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.46ms,28.08us,96.00ns,28.56us,1.70us,27.88us,51.40us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.51ms,82.08us,1.62us,82.39us,2.71us,78.19us,106.63us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.70ms,137.64us,101.00ns,138.91us,2.44us,137.31us,158.59us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,401.06ms,328.53us,4.88us,329.91us,6.83us,317.93us,405.88us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.14ms,363.22us,2.42us,363.10us,4.54us,354.49us,391.87us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.78ms,132.84us,442.00ns,134.17us,2.70us,131.90us,150.09us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.94ms,297.83us,668.00ns,300.81us,4.53us,296.85us,347.91us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,958,601.32ms,522.83us,4.77us,521.83us,6.95us,508.50us,552.73us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.55ms,74.91us,343.00ns,75.77us,3.18us,74.09us,149.47us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.50ms,2.27ms,7.73us,2.27ms,11.68us,2.25ms,2.33ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,551.28ms,483.40us,4.07us,483.44us,5.12us,474.99us,528.43us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,87,751.41ms,5.79ms,14.19us,5.80ms,22.82us,5.74ms,5.88ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,727,601.32ms,687.63us,4.12us,688.48us,6.67us,675.10us,720.30us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,53,751.52ms,9.43ms,25.25us,9.44ms,51.12us,9.36ms,9.67ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,304,701.41ms,1.64ms,9.32us,1.65ms,13.76us,1.62ms,1.69ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.63ms,86.44us,3.45us,89.54us,6.58us,81.64us,106.80us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.49ms,13.12us,26.00ns,13.29us,1.10us,13.01us,26.50us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.50ms,66.30us,44.00ns,66.95us,1.78us,66.12us,78.80us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.50ms,85.45us,1.91us,87.33us,5.22us,80.96us,107.56us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.45ms,13.10us,27.00ns,13.39us,1.73us,12.99us,38.11us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.55ms,66.37us,54.00ns,67.05us,1.87us,66.19us,84.70us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.58ms,48.95us,360.00ns,49.82us,2.60us,48.19us,67.66us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.62ms,95.18us,911.00ns,96.29us,3.14us,93.07us,120.43us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.55ms,83.20us,140.00ns,84.10us,1.86us,82.94us,95.39us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.58ms,46.75us,362.00ns,47.84us,3.09us,45.99us,70.37us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.74ms,94.35us,650.00ns,95.33us,2.33us,92.92us,105.19us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.53ms,83.93us,138.00ns,84.79us,1.97us,83.56us,99.94us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,652,651.35ms,768.65us,2.13us,766.11us,10.99us,744.44us,924.57us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,770,601.42ms,647.70us,3.49us,649.47us,5.95us,642.25us,711.45us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,525,651.46ms,0.95ms,1.27us,0.95ms,6.06us,939.72us,1.04ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,275,751.62ms,1.82ms,2.54us,1.82ms,7.38us,1.81ms,1.87ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,123,751.50ms,4.08ms,25.10us,4.09ms,47.87us,4.00ms,4.36ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,378,701.50ms,1.32ms,7.67us,1.33ms,16.66us,1.30ms,1.48ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,751.52ms,55.67ms,122.07us,55.69ms,151.82us,55.49ms,55.96ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,751.49ms,20.48ms,36.88us,20.52ms,75.97us,20.43ms,20.74ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.63ms,105.21us,1.15us,106.92us,10.08us,102.73us,393.65us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.53ms,57.91us,1.08us,58.88us,2.92us,56.26us,107.56us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.54ms,75.42us,59.00ns,76.19us,1.93us,75.22us,90.10us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.52ms,56.98us,273.00ns,57.86us,2.50us,56.30us,75.27us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.54ms,75.71us,2.22us,76.38us,3.44us,72.22us,96.56us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.66ms,111.53us,145.00ns,112.58us,2.19us,111.04us,129.52us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.58ms,113.90us,1.26us,115.53us,3.91us,111.80us,147.53us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.44ms,37.83us,248.00ns,38.27us,1.61us,37.26us,51.23us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.48ms,77.03us,60.00ns,77.85us,2.15us,76.82us,103.75us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.01ms,367.56us,4.64us,369.79us,33.26us,359.31us,1.40ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,181,751.56ms,2.76ms,6.64us,2.77ms,132.69us,2.73ms,4.33ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,935,601.30ms,534.63us,2.01us,534.99us,3.96us,526.39us,576.48us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.96ms,229.45us,3.20us,230.68us,20.97us,223.37us,869.86us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,337,701.46ms,1.48ms,8.87us,1.49ms,17.28us,1.46ms,1.57ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.92ms,243.88us,2.47us,245.23us,30.03us,240.18us,1.04ms -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,501.13ms,420.46us,2.28us,421.00us,4.52us,410.98us,446.35us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.33ms,470.53us,4.13us,470.79us,6.05us,454.88us,511.67us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,963,601.38ms,518.84us,3.38us,519.47us,5.31us,508.10us,543.09us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.52ms,84.20us,1.74us,86.37us,4.58us,81.19us,103.02us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.43ms,37.89us,195.00ns,38.25us,1.42us,37.27us,50.60us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.55ms,66.18us,45.00ns,66.84us,1.92us,66.01us,92.12us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.58ms,48.02us,558.00ns,48.97us,2.92us,47.09us,68.14us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.45ms,36.14us,71.00ns,36.58us,1.62us,35.86us,53.27us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.63ms,83.25us,86.00ns,84.19us,3.13us,82.96us,145.94us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,301.19ms,224.89us,2.98us,225.66us,4.46us,216.92us,243.16us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.46ms,45.78us,119.00ns,46.25us,2.04us,45.26us,73.25us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.46ms,81.97us,1.68us,82.21us,2.71us,78.23us,104.01us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.54ms,137.77us,119.00ns,139.00us,2.31us,137.43us,153.29us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,201.07ms,124.24us,4.10us,126.25us,10.05us,118.43us,225.21us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,400.83ms,333.09us,4.48us,334.78us,8.51us,322.57us,445.24us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.57ms,135.41us,744.00ns,136.59us,2.85us,134.00us,158.31us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,351.65ms,300.81us,1.99us,300.19us,3.76us,295.93us,331.79us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,601.89ms,456.95us,3.54us,457.68us,7.56us,444.02us,589.24us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.54ms,95.25us,2.33us,96.08us,4.17us,90.81us,133.62us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.12ms,2.27ms,6.04us,2.28ms,10.20us,2.25ms,2.31ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,550.98ms,481.75us,2.79us,482.38us,4.72us,472.86us,513.94us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,979,752.15ms,518.35us,20.21us,510.31us,20.44us,480.74us,554.06us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,798,601.86ms,623.98us,3.96us,626.64us,20.50us,609.17us,0.97ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,752.05ms,9.40ms,16.17us,9.42ms,84.63us,9.36ms,9.97ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,304,701.11ms,1.64ms,8.88us,1.64ms,14.10us,1.62ms,1.71ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,151.30ms,88.09us,1.55us,88.70us,4.12us,82.82us,111.94us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.37ms,20.61us,74.00ns,20.87us,1.37us,20.39us,37.98us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.40ms,66.17us,46.00ns,66.81us,1.91us,66.01us,87.37us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.51ms,88.00us,2.68us,89.83us,5.89us,83.01us,114.44us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.37ms,20.10us,60.00ns,20.37us,1.34us,19.93us,37.74us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.42ms,66.23us,45.00ns,66.96us,2.13us,66.06us,92.49us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.33ms,24.27us,124.00ns,24.71us,1.79us,23.98us,38.90us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.40ms,83.34us,54.00ns,84.23us,2.24us,83.19us,103.35us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.40ms,83.04us,70.00ns,83.91us,2.46us,82.82us,123.50us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.36ms,24.36us,101.00ns,24.77us,1.76us,24.07us,39.11us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.44ms,83.39us,65.00ns,84.37us,2.75us,83.18us,114.56us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.43ms,83.50us,64.00ns,84.31us,2.10us,83.28us,103.93us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,700,802.18ms,712.98us,6.43us,713.44us,8.94us,701.75us,753.99us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,757,601.24ms,658.18us,3.34us,660.55us,7.12us,646.91us,707.40us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,546,652.15ms,914.55us,1.38us,915.59us,8.06us,901.82us,0.97ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,275,752.33ms,1.82ms,4.50us,1.82ms,7.78us,1.81ms,1.85ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,127,1.55s,3.95ms,39.87us,3.95ms,48.74us,3.81ms,4.05ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,267,751.42ms,1.88ms,2.48us,1.88ms,8.81us,1.86ms,1.92ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,752.02ms,55.97ms,83.66us,55.93ms,182.66us,55.48ms,56.10ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,751.31ms,20.45ms,47.37us,20.49ms,160.46us,20.37ms,21.20ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,151.38ms,106.33us,2.28us,106.48us,3.36us,101.44us,124.57us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.43ms,57.62us,845.00ns,58.67us,2.71us,56.15us,84.03us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,101.32ms,75.49us,53.00ns,76.23us,2.04us,75.31us,97.64us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.45ms,41.48us,213.00ns,42.37us,3.04us,40.87us,70.49us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.44ms,75.96us,2.17us,76.58us,3.39us,71.91us,97.76us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.48ms,111.44us,156.00ns,112.42us,2.20us,110.91us,129.24us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.50ms,113.00us,830.00ns,113.82us,3.35us,109.21us,137.18us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.35ms,37.17us,88.00ns,37.73us,1.95us,36.91us,54.98us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,101.25ms,77.05us,55.00ns,77.86us,2.27us,76.84us,96.73us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,450.84ms,339.94us,2.43us,339.99us,4.51us,331.93us,372.13us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,182,751.19ms,2.75ms,6.56us,2.75ms,10.49us,2.74ms,2.79ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,941,601.93ms,531.22us,2.97us,531.37us,5.24us,518.75us,596.83us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.67ms,207.34us,3.03us,207.71us,4.38us,200.22us,231.67us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,337,652.04ms,1.48ms,10.09us,1.49ms,19.87us,1.46ms,1.63ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.67ms,243.45us,2.35us,243.12us,2.94us,239.81us,260.11us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,350.71ms,308.28us,3.58us,308.24us,5.48us,293.65us,329.30us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,550.99ms,467.03us,4.19us,467.55us,6.91us,452.37us,541.04us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,967,601.04ms,516.94us,3.46us,517.44us,5.15us,505.99us,551.90us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.49ms,88.16us,1.49us,88.45us,3.54us,82.80us,113.46us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.37ms,37.64us,188.00ns,38.09us,1.84us,37.16us,62.31us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.40ms,66.22us,48.00ns,66.91us,2.07us,66.05us,85.93us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.37ms,24.30us,78.00ns,24.73us,1.93us,24.08us,47.26us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.34ms,36.18us,87.00ns,36.67us,2.12us,35.84us,59.67us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.65us,76.00ns,84.40us,2.00us,83.34us,105.73us diff --git a/audit/rebar/results/spr/rebar-audit-pass3.csv b/audit/rebar/results/spr/rebar-audit-pass3.csv index fd909b6..641ea14 100644 --- a/audit/rebar/results/spr/rebar-audit-pass3.csv +++ b/audit/rebar/results/spr/rebar-audit-pass3.csv @@ -1,61 +1,61 @@ name,model,rebar_version,engine,engine_version,err,haystack_len,iters,total,median,mad,mean,stddev,min,max -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,300.83ms,248.97us,3.06us,249.11us,4.65us,241.68us,276.62us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,50.44ms,28.03us,218.00ns,28.57us,1.71us,27.52us,50.80us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.47ms,81.85us,1.56us,82.07us,2.69us,77.92us,102.95us -curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.70ms,138.10us,575.00ns,139.49us,3.24us,137.29us,203.59us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,401.00ms,333.76us,4.83us,335.23us,6.26us,323.00us,368.30us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,1000,451.11ms,363.09us,2.31us,362.92us,4.24us,354.62us,389.73us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.69ms,132.24us,370.00ns,133.75us,2.74us,131.37us,158.14us -curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.91ms,300.54us,2.85us,300.44us,4.33us,296.43us,379.42us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,951,601.30ms,526.79us,4.82us,525.84us,6.75us,510.57us,549.44us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,899232,1000,100.56ms,74.86us,231.00ns,75.73us,2.30us,74.17us,89.43us -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.59ms,2.27ms,7.21us,2.27ms,11.66us,2.25ms,2.32ms -curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,551.28ms,484.29us,1.65us,484.42us,4.84us,476.96us,599.34us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,78,751.51ms,6.41ms,14.00us,6.41ms,21.79us,6.37ms,6.46ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,1570556,728,601.35ms,686.85us,4.14us,686.75us,7.33us,669.38us,711.92us -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.54ms,9.40ms,19.12us,9.42ms,80.50us,9.33ms,9.79ms -curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,302,701.52ms,1.65ms,13.75us,1.66ms,52.10us,1.62ms,2.29ms -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.54ms,84.37us,1.06us,86.15us,4.36us,81.59us,112.62us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.44ms,13.18us,24.00ns,13.48us,1.70us,13.09us,38.00us -hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.51ms,66.18us,46.00ns,66.83us,1.83us,66.00us,85.35us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.64ms,86.68us,4.01us,89.03us,6.34us,80.90us,112.53us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613357,1000,50.53ms,13.14us,21.00ns,13.34us,1.30us,13.05us,32.45us -hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.53ms,66.27us,50.00ns,66.97us,1.93us,66.10us,80.95us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.57ms,47.35us,264.00ns,48.41us,3.09us,46.77us,73.82us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.64ms,93.24us,564.00ns,94.54us,3.04us,91.99us,107.88us -hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.55ms,83.06us,98.00ns,83.93us,2.19us,82.76us,110.94us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.53ms,47.24us,406.00ns,48.19us,3.05us,46.42us,69.94us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,613423,1000,150.68ms,93.72us,768.00ns,94.92us,3.11us,92.40us,124.10us -hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.53ms,83.31us,88.00ns,84.14us,1.96us,83.03us,97.48us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,653,651.36ms,765.66us,5.87us,765.55us,12.95us,735.27us,0.98ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,771,601.43ms,652.45us,4.56us,648.92us,7.72us,636.06us,679.16us -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,525,651.52ms,0.95ms,1.64us,0.95ms,5.59us,939.71us,0.98ms -imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,275,751.64ms,1.82ms,2.08us,1.82ms,8.51us,1.80ms,1.86ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,123,752.08ms,4.09ms,20.88us,4.10ms,33.95us,4.02ms,4.21ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2024-04-19,,16013977,378,701.48ms,1.32ms,6.38us,1.32ms,16.04us,1.30ms,1.55ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,751.58ms,55.82ms,101.70us,55.78ms,149.09us,55.45ms,55.97ms -imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,751.63ms,20.50ms,26.26us,20.51ms,48.66us,20.42ms,20.62ms -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.64ms,107.09us,1.77us,107.73us,3.66us,101.84us,160.75us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.58ms,58.49us,1.11us,59.35us,2.47us,56.85us,84.29us -imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.55ms,75.42us,54.00ns,76.13us,1.82us,75.18us,88.55us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.52ms,56.87us,288.00ns,57.76us,2.63us,56.15us,82.44us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.58ms,77.08us,2.35us,77.53us,3.51us,72.68us,100.72us -imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.64ms,111.46us,152.00ns,112.48us,2.13us,111.03us,126.95us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.58ms,114.24us,1.30us,115.77us,3.90us,112.17us,144.10us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.45ms,37.62us,286.00ns,38.09us,1.73us,37.04us,55.17us -imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.50ms,77.03us,60.00ns,77.75us,1.83us,76.79us,90.94us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,451.16ms,368.74us,3.77us,369.06us,6.04us,360.07us,444.34us -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,182,751.66ms,2.76ms,6.97us,2.76ms,11.34us,2.73ms,2.79ms -imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,937,601.49ms,533.76us,2.09us,534.04us,3.86us,524.38us,565.72us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.90ms,229.27us,3.15us,230.36us,15.27us,223.33us,676.69us -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,335,701.54ms,1.49ms,13.00us,1.49ms,30.36us,1.46ms,1.85ms -imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.89ms,243.35us,2.19us,243.57us,2.98us,240.31us,274.45us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,501.22ms,420.40us,3.98us,420.94us,5.84us,411.18us,510.08us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,551.34ms,466.39us,4.83us,466.71us,6.90us,450.44us,499.53us -imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,964,601.47ms,519.60us,4.64us,518.83us,5.82us,507.67us,548.63us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,100.57ms,84.05us,1.53us,85.71us,3.96us,80.79us,113.40us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.43ms,37.90us,218.00ns,38.44us,2.16us,37.34us,58.07us -opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.51ms,66.18us,45.00ns,66.81us,1.80us,66.00us,87.48us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,100.58ms,46.35us,116.00ns,47.18us,2.67us,45.95us,64.31us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.50ms,36.15us,92.00ns,36.52us,1.53us,35.78us,57.23us -opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.57ms,83.25us,92.00ns,84.18us,3.48us,82.84us,167.80us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,301.30ms,224.72us,3.27us,225.45us,4.52us,217.26us,242.04us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,100.46ms,45.19us,113.00ns,45.69us,2.01us,44.70us,65.27us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,1000,100.40ms,81.90us,1.48us,82.21us,2.92us,78.08us,106.81us +curated/01-literal/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,200.58ms,137.62us,98.00ns,138.94us,2.51us,137.33us,157.03us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,1000,201.38ms,122.06us,1.77us,123.48us,4.51us,118.34us,163.14us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,1000,400.81ms,332.04us,4.61us,333.15us,7.07us,321.16us,367.55us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,1000,200.59ms,135.63us,2.14us,136.12us,3.62us,131.38us,159.48us +curated/01-literal/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,1000,350.78ms,301.59us,2.41us,301.10us,3.84us,296.02us,332.44us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,899232,1000,601.82ms,461.65us,3.63us,462.14us,5.99us,448.16us,488.08us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,899232,1000,150.51ms,94.02us,2.12us,94.82us,3.91us,90.45us,135.77us +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,899232,220,751.19ms,2.28ms,7.15us,2.28ms,10.71us,2.26ms,2.33ms +curated/02-literal-alternate/sherlock-casei-en,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,899232,1000,550.98ms,481.81us,2.24us,482.19us,4.46us,473.64us,512.79us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,1570556,968,751.92ms,525.00us,7.92us,516.32us,18.82us,480.55us,550.22us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,1570556,800,601.05ms,623.43us,3.67us,624.97us,7.53us,610.85us,661.34us +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,1570556,54,751.19ms,9.39ms,25.79us,9.40ms,46.41us,9.33ms,9.54ms +curated/02-literal-alternate/sherlock-casei-ru,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,1570556,305,702.08ms,1.64ms,9.04us,1.64ms,14.02us,1.61ms,1.69ms +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.51ms,87.99us,2.13us,88.15us,3.72us,82.98us,111.64us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.36ms,19.80us,37.00ns,20.00us,1.16us,19.63us,38.50us +hyperscan/literal-casei-english-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.43ms,66.20us,42.00ns,66.80us,1.69us,66.03us,82.49us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.47ms,87.96us,2.15us,88.50us,4.44us,82.70us,112.31us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613357,1000,50.36ms,20.04us,43.00ns,20.25us,1.14us,19.84us,36.99us +hyperscan/literal-casei-english-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.40ms,66.23us,43.00ns,66.89us,1.97us,66.08us,88.99us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.38ms,24.52us,105.00ns,24.91us,1.78us,24.24us,39.49us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.38ms,83.37us,83.00ns,84.26us,2.30us,83.21us,108.75us +hyperscan/literal-casei-russian-nosom,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.64us,77.00ns,84.49us,2.63us,83.40us,135.56us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.34ms,24.50us,253.00ns,24.99us,1.72us,24.16us,38.06us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,613423,1000,100.38ms,83.32us,78.00ns,84.17us,2.18us,83.12us,110.87us +hyperscan/literal-casei-russian-som,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.75us,88.00ns,84.61us,2.29us,83.45us,107.66us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,698,801.74ms,712.43us,5.39us,715.61us,10.48us,703.83us,820.72us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,757,601.18ms,657.98us,3.17us,660.38us,7.20us,646.95us,708.42us +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,546,652.23ms,914.88us,1.50us,916.01us,7.38us,904.09us,0.96ms +imported/leipzig/twain-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,275,752.33ms,1.82ms,3.27us,1.82ms,7.71us,1.81ms,1.86ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,16013977,127,1.55s,3.95ms,31.32us,3.95ms,47.51us,3.84ms,4.05ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),hyperscan,5.4.2 2026-08-25,,16013977,267,751.38ms,1.88ms,3.75us,1.88ms,10.11us,1.86ms,1.92ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,16013977,9,752.23ms,55.56ms,39.16us,55.57ms,97.10us,55.40ms,55.78ms +imported/leipzig/tom-sawyer-huckle-fin-insensitive,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,16013977,25,752.26ms,20.47ms,30.72us,20.48ms,36.31us,20.41ms,20.57ms +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,151.37ms,106.39us,2.16us,106.69us,3.17us,101.79us,124.36us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,100.42ms,57.87us,1.10us,58.73us,2.47us,56.13us,79.07us +imported/sherlock/name-sherlock-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.44ms,75.44us,55.00ns,76.27us,2.20us,75.27us,93.94us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,100.42ms,41.69us,266.00ns,42.30us,2.14us,41.06us,74.89us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,101.31ms,76.18us,2.17us,76.70us,3.19us,72.23us,101.42us +imported/sherlock/name-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,150.47ms,111.53us,120.00ns,112.51us,2.25us,111.14us,138.39us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,150.49ms,113.17us,1.12us,113.87us,3.45us,109.09us,134.58us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,50.34ms,37.92us,268.00ns,38.32us,1.93us,37.19us,66.71us +imported/sherlock/name-sherlock-holmes-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,100.36ms,77.09us,57.00ns,77.82us,1.96us,76.88us,98.17us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,450.96ms,339.26us,2.11us,339.56us,3.99us,331.77us,364.75us +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,182,751.16ms,2.75ms,7.41us,2.75ms,11.54us,2.73ms,2.81ms +imported/sherlock/name-alt3-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,934,601.93ms,535.57us,2.76us,535.55us,5.14us,522.05us,571.82us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,300.63ms,206.74us,2.36us,207.39us,3.91us,200.08us,236.78us +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,337,701.15ms,1.48ms,9.16us,1.49ms,21.12us,1.46ms,1.58ms +imported/sherlock/name-alt5-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,1000,300.69ms,243.57us,2.25us,243.46us,3.00us,240.18us,272.24us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,594933,1000,350.73ms,307.59us,3.52us,308.08us,5.73us,294.06us,343.10us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,594933,1000,550.99ms,465.32us,4.18us,465.51us,6.83us,450.91us,524.66us +imported/sherlock/the-casei,count-spans,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,594933,968,602.06ms,516.26us,2.35us,516.79us,4.54us,507.90us,573.94us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613357,1000,150.50ms,87.89us,2.15us,88.01us,3.35us,83.21us,116.72us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613357,1000,50.40ms,37.82us,213.00ns,38.28us,1.88us,37.33us,54.65us +opt/prefilter/literal-casei-english,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613357,1000,100.41ms,66.29us,46.00ns,66.97us,2.00us,66.14us,85.22us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),casei,casei-rebar 1,,613423,1000,50.37ms,23.88us,56.00ns,24.32us,1.83us,23.67us,38.35us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),pcre2/jit,10.47 2025-10-21,,613423,1000,50.34ms,36.09us,82.00ns,36.56us,2.12us,35.81us,61.78us +opt/prefilter/literal-casei-russian,count,0.1.0 (rev 463d00f318),rust/regex,1.12.4,,613423,1000,100.41ms,83.74us,84.00ns,84.57us,2.40us,83.47us,128.02us diff --git a/audit/rebar/runner/main.go b/audit/rebar/runner/main.go index 9c6af78..6dad97f 100644 --- a/audit/rebar/runner/main.go +++ b/audit/rebar/runner/main.go @@ -51,7 +51,7 @@ func run() error { if !c.caseInsensitive { return errors.New("casei runner only accepts case-insensitive benchmarks") } - if c.model != "count" && c.model != "count-spans" { + if c.model != "count" && c.model != "count-spans" && c.model != "find" { return fmt.Errorf("unsupported model %q", c.model) } patterns, err := literalAlternation(c.patterns) @@ -59,15 +59,20 @@ func run() error { return err } matcher := casei.NewMatcher(patterns) - bench := func() (int, error) { - return countMatches(c.haystack, patterns, matcher, c.model == "count-spans") + spans := c.model == "count-spans" + if _, err := verifyEnumeration(c.haystack, patterns, matcher, spans); err != nil { + return err + } + bench := func() int { + if c.model == "find" { + return findMatch(c.haystack, matcher) + } + return countMatches(c.haystack, matcher, spans) } warmupStart := time.Now() for i := uint64(0); i < c.maxWarmupIters; i++ { - if _, err := bench(); err != nil { - return err - } + _ = bench() if time.Since(warmupStart) >= c.maxWarmupTime { break } @@ -77,11 +82,8 @@ func run() error { runStart := time.Now() for i := uint64(0); i < c.maxIters; i++ { start := time.Now() - count, err := bench() + count := bench() duration := time.Since(start) - if err != nil { - return err - } fmt.Fprintf(out, "%d,%d\n", duration.Nanoseconds(), count) if time.Since(runStart) >= c.maxTime { break @@ -90,28 +92,34 @@ func run() error { return out.Flush() } -func countMatches(haystack string, patterns []string, matcher *casei.Matcher, spans bool) (int, error) { +// findMatch is the timed single-query operation for Find-shaped workloads. +// verifyEnumeration still validates the complete non-overlapping contract once +// before the runner starts its warm-up and measurement loops. +func findMatch(haystack string, matcher *casei.Matcher) int { + if _, ok := matcher.Find(haystack); ok { + return 1 + } + return 0 +} + +// countMatches is the timed Rebar operation: one compiled Matcher enumeration +// and only the count/span sink. verifyEnumeration runs the independent oracle +// once before the runner starts its warm-up and measurement loops. +func countMatches(haystack string, matcher *casei.Matcher, spans bool) int { total := 0 - for at := 0; at <= len(haystack); { - match, ok := matcher.Find(haystack[at:]) - if !ok { - break - } - start := at + match.Start - width, ok := foldPrefixWidth(haystack[start:], patterns[match.Pattern]) - if !ok || width == 0 { - return 0, fmt.Errorf("casei returned an unverifiable match at %d for pattern %q", start, patterns[match.Pattern]) - } + matcher.Each(haystack, func(_ casei.Match, width int) bool { if spans { total += width } else { total++ } - at = start + width - } - return total, nil + return true + }) + return total } +// foldPrefixWidth is deliberately independent from Matcher.Each. The Rebar +// preflight uses it to verify every source width and match boundary. func foldPrefixWidth(haystack, pattern string) (int, bool) { consumed := 0 for len(pattern) > 0 { @@ -149,6 +157,61 @@ func foldEqual(a, b rune) bool { return false } +// nextMatch is a package-independent, source-boundary oracle for the next +// non-empty literal occurrence. At one source offset, the first matching +// pattern index wins; offsets are then considered left to right. +func nextMatch(haystack string, patterns []string, from int) (casei.Match, int, bool) { + for at := from; at <= len(haystack); { + for pattern, literal := range patterns { + if width, ok := foldPrefixWidth(haystack[at:], literal); ok && width != 0 { + return casei.Match{Pattern: pattern, Start: at}, width, true + } + } + if at == len(haystack) { + break + } + _, size := utf8.DecodeRuneInString(haystack[at:]) + at += size + } + return casei.Match{}, 0, false +} + +// verifyEnumeration compares every result to the canonical source scan before +// timing begins. It validates Pattern bounds, leftmost/lowest-ID order, exact +// source width, and the non-overlapping resume point without using Matcher.Find. +func verifyEnumeration(haystack string, patterns []string, matcher *casei.Matcher, spans bool) (int, error) { + at, total := 0, 0 + var verifyErr error + complete := matcher.Each(haystack, func(match casei.Match, width int) bool { + if match.Pattern < 0 || match.Pattern >= len(patterns) || match.Start < at || match.Start > len(haystack) || width <= 0 { + verifyErr = fmt.Errorf("casei returned invalid match %+v with width %d", match, width) + return false + } + want, expectedWidth, ok := nextMatch(haystack, patterns, at) + if !ok || match != want || width != expectedWidth { + verifyErr = fmt.Errorf("casei returned match %+v with width %d; canonical next match is %+v with width %d, ok=%t", match, width, want, expectedWidth, ok) + return false + } + if spans { + total += width + } else { + total++ + } + at = match.Start + width + return true + }) + if verifyErr != nil { + return 0, verifyErr + } + if !complete { + return 0, errors.New("casei enumeration stopped during preflight") + } + if want, width, ok := nextMatch(haystack, patterns, at); ok { + return 0, fmt.Errorf("casei omitted canonical match %+v with width %d", want, width) + } + return total, nil +} + func literalAlternation(raw []string) ([]string, error) { if len(raw) != 1 { return nil, fmt.Errorf("expected one rebar regex, got %d", len(raw)) diff --git a/audit/rebar/runner/main_test.go b/audit/rebar/runner/main_test.go index 9b3a284..d71b93f 100644 --- a/audit/rebar/runner/main_test.go +++ b/audit/rebar/runner/main_test.go @@ -28,7 +28,7 @@ func TestLiteralAlternation(t *testing.T) { } } -func TestFoldPrefixWidth(t *testing.T) { +func TestEachWidth(t *testing.T) { for _, tt := range []struct { haystack string pattern string @@ -38,15 +38,36 @@ func TestFoldPrefixWidth(t *testing.T) { {"Kelvin", "k", 3, true}, {"ſuffix", "S", 2, true}, {"ς", "Σ", 2, true}, + {"шЕРЛОК хОЛМС", "Шерлок Холмс", len("шЕРЛОК хОЛМС"), true}, + {"Ёлка", "ёлка", len("Ёлка"), true}, {"x", "s", 0, false}, {string([]byte{0xff}), string([]byte{0xff}), 1, true}, {string([]byte{0xfe}), string([]byte{0xff}), 0, false}, } { - width, ok := foldPrefixWidth(tt.haystack, tt.pattern) - if width != tt.width || ok != tt.ok { - t.Errorf("foldPrefixWidth(%q, %q) = (%d, %v), want (%d, %v)", - tt.haystack, tt.pattern, width, ok, tt.width, tt.ok) + expected, expectedOK := foldPrefixWidth(tt.haystack, tt.pattern) + if expected != tt.width || expectedOK != tt.ok { + t.Fatalf("foldPrefixWidth(%q, %q) = (%d, %v), want (%d, %v)", + tt.haystack, tt.pattern, expected, expectedOK, tt.width, tt.ok) } + got, ok := 0, false + casei.NewMatcher([]string{tt.pattern}).Each(tt.haystack, func(_ casei.Match, width int) bool { + got, ok = width, true + return false + }) + if got != expected || ok != expectedOK { + t.Errorf("Each(%q, %q) = (%d, %v), want independently verified (%d, %v)", + tt.haystack, tt.pattern, got, ok, expected, expectedOK) + } + } +} + +func TestFindMatch(t *testing.T) { + matcher := casei.NewMatcher([]string{"needle"}) + if got := findMatch("a needle", matcher); got != 1 { + t.Fatalf("findMatch(hit) = %d, want 1", got) + } + if got := findMatch("a haystack", matcher); got != 0 { + t.Fatalf("findMatch(miss) = %d, want 0", got) } } @@ -60,10 +81,10 @@ func TestCountMatches(t *testing.T) { {false, 2}, {true, 5}, } { - got, err := countMatches("SSſs", patterns, matcher, tt.spans) - if err != nil { - t.Fatal(err) + if got, err := verifyEnumeration("SSſs", patterns, matcher, tt.spans); err != nil || got != tt.want { + t.Fatalf("verifyEnumeration(spans=%v) = %d, %v; want %d, nil", tt.spans, got, err, tt.want) } + got := countMatches("SSſs", matcher, tt.spans) if got != tt.want { t.Fatalf("countMatches(spans=%v) = %d, want %d", tt.spans, got, tt.want) } diff --git a/casei_test.go b/casei_test.go index 5e2f4e7..9c74796 100644 --- a/casei_test.go +++ b/casei_test.go @@ -305,6 +305,9 @@ func FuzzIndexFold(f *testing.F) { f.Add("große", "GROSSE") f.Add(strings.Repeat("ab", 64), "abc") f.Add("na\xc3\xafve", "\xc3\x8f") + f.Add(strings.Repeat("x", 64)+"ПРИКЛЮЧЕНИЯ ЛИЛИЙ"+strings.Repeat("x", 4096), "приключения лилий") + f.Add(strings.Repeat("x", 64)+"приключения лилия"+"x"+"ПРИКЛЮЧЕНИЯ ЛИЛИЙ"+strings.Repeat("x", 4096), "приключения лилий") + f.Add(strings.Repeat("x", 64)+"\x80ПРИКЛЮЧЕНИЯ ЛИЛИЙ"+strings.Repeat("x", 4096), "\x80приключения лилий") f.Fuzz(func(t *testing.T, haystack, needle string) { got, want := IndexFold(haystack, needle), reference(haystack, needle) if got != want { diff --git a/each_harness_test.go b/each_harness_test.go new file mode 100644 index 0000000..fa7a1fc --- /dev/null +++ b/each_harness_test.go @@ -0,0 +1,38 @@ +package casei + +import "testing" + +// TestEachHarnessContract fixes the public enumeration reduction that the +// Rebar adapter times. The optimized implementation must preserve this +// repeated-Find baseline's non-overlap order and source widths. +func TestEachHarnessContract(t *testing.T) { + matcher := NewMatcher([]string{"ss", "s"}) + want := []struct { + match Match + width int + }{ + {Match{Pattern: 0, Start: 0}, len("SS")}, + {Match{Pattern: 0, Start: len("SS")}, len("ſs")}, + } + var got []struct { + match Match + width int + } + if complete := matcher.Each("SSſs", func(match Match, width int) bool { + got = append(got, struct { + match Match + width int + }{match, width}) + return true + }); !complete { + t.Fatal("Each stopped before completing enumeration") + } + if len(got) != len(want) { + t.Fatalf("Each returned %d matches, want %d", len(got), len(want)) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("match %d = %+v, want %+v", i, got[i], want[i]) + } + } +} diff --git a/matcher.go b/matcher.go index 7cfbb10..50dd1aa 100644 --- a/matcher.go +++ b/matcher.go @@ -1,5 +1,7 @@ package casei +import "unicode/utf8" + // Matcher searches for any of a set of patterns under the same Unicode // simple-fold semantics as IndexFold. IndexFold is the one-pattern form of the // same compiled search plan. The implementation scans the haystack once rather @@ -16,8 +18,8 @@ type Match struct { } // Matcher searches for any of a fixed set of patterns. Construction compiles -// their shared fold-orbit transition plan; Find only advances that plan over -// the haystack. +// their shared fold-orbit transition plan; Find returns one answer and Each +// enumerates non-overlapping answers over the haystack. type Matcher struct { patterns []string plan *searchPlan @@ -48,6 +50,57 @@ func (m *Matcher) Find(haystack string) (Match, bool) { return m.plan.find(haystack) } +// Each calls yield for each non-overlapping match in haystack, in the same +// leftmost and lowest-pattern-ID order as repeated calls to Find. width is the +// exact byte width consumed by this occurrence, which can differ from the +// matched pattern's byte length under Unicode simple folding. Returning false +// from yield stops enumeration and makes Each return false. +// +// A nil Matcher or nil yield has no matches and returns true. Each is safe for +// concurrent use when yield itself is safe. +func (m *Matcher) Each(haystack string, yield func(match Match, width int) bool) bool { + if m == nil || m.plan == nil || yield == nil { + return true + } + if m.plan.empty < 0 && m.plan.rawByteMulti.usable() { + return m.plan.eachRawByteFixedAnchored(haystack, yield) + } + for at := 0; at <= len(haystack); { + match, width, ok := m.plan.findWithWidth(haystack[at:]) + if !ok { + return true + } + match.Start += at + if width == 0 { + units := utf8.RuneCountInString(m.patterns[match.Pattern]) + width = matcherMatchEnd(haystack, match.Start, units) - match.Start + } + end := match.Start + width + if !yield(match, width) { + return false + } + if width != 0 { + at = end + continue + } + if match.Start == len(haystack) { + return true + } + _, size := utf8.DecodeRuneInString(haystack[match.Start:]) + at = match.Start + size + } + return true +} + +func matcherMatchEnd(haystack string, start, units int) int { + at := start + for range units { + _, size := utf8.DecodeRuneInString(haystack[at:]) + at += size + } + return at +} + // VectorBits reports the widest runtime-gated block transition available to // this package, with the same contract as RuntimeVectorBits. func (m *Matcher) VectorBits() int { return RuntimeVectorBits() } diff --git a/matcher_test.go b/matcher_test.go index 73924f5..493d134 100644 --- a/matcher_test.go +++ b/matcher_test.go @@ -6,6 +6,7 @@ import ( "strings" "sync" "testing" + "unicode/utf8" ) // refFind is the independent multi-needle reference: per-pattern canonical @@ -27,6 +28,42 @@ func refFind(haystack string, patterns []string) (Match, bool) { return best, true } +type refEachResult struct { + match Match + width int +} + +// refEach repeats the independent refFind oracle and advances by decoded +// source units. It is deliberately separate from Matcher.findWithWidth, whose +// optimized raw confirmation can return the width without decoding again. +func refEach(haystack string, patterns []string) []refEachResult { + var results []refEachResult + for from := 0; from <= len(haystack); { + match, ok := refFind(haystack[from:], patterns) + if !ok { + return results + } + match.Start += from + end := match.Start + for range utf8.RuneCountInString(patterns[match.Pattern]) { + _, size := utf8.DecodeRuneInString(haystack[end:]) + end += size + } + width := end - match.Start + results = append(results, refEachResult{match: match, width: width}) + if width != 0 { + from = end + continue + } + if match.Start == len(haystack) { + return results + } + _, size := utf8.DecodeRuneInString(haystack[match.Start:]) + from = match.Start + size + } + return results +} + var matcherTraps = []struct { name string haystack string @@ -552,10 +589,28 @@ func FuzzMatcher(f *testing.F) { f.Add("доктор Ватсон", "ватсон", "ШЕРЛОК", "z") f.Fuzz(func(t *testing.T, haystack, p0, p1, p2 string) { pats := []string{p0, p1, p2} - got, gotOK := NewMatcher(pats).Find(haystack) + matcher := NewMatcher(pats) + got, gotOK := matcher.Find(haystack) want, wantOK := refFind(haystack, pats) if gotOK != wantOK || (gotOK && got != want) { t.Fatalf("Find(%q, %q) = %+v,%v want %+v,%v", haystack, pats, got, gotOK, want, wantOK) } + + var gotEach []refEachResult + if complete := matcher.Each(haystack, func(match Match, width int) bool { + gotEach = append(gotEach, refEachResult{match: match, width: width}) + return true + }); !complete { + t.Fatal("Each stopped with a callback that always returns true") + } + wantEach := refEach(haystack, pats) + if len(gotEach) != len(wantEach) { + t.Fatalf("Each(%q, %q) returned %d matches, want %d: got=%+v want=%+v", haystack, pats, len(gotEach), len(wantEach), gotEach, wantEach) + } + for i := range wantEach { + if gotEach[i] != wantEach[i] { + t.Fatalf("Each(%q, %q) match %d = %+v, want %+v", haystack, pats, i, gotEach[i], wantEach[i]) + } + } }) } diff --git a/plan.go b/plan.go index 3422f2d..15df4d0 100644 --- a/plan.go +++ b/plan.go @@ -40,35 +40,43 @@ type searchPlan struct { // asciiProbe is a single-pattern, byte-aligned block transition. It // intersects three dispersed literal positions, then confirms the same // compiled pattern at the surviving start. - asciiProbe asciiProbe - asciiOnlyProbe asciiProbe - asciiOnlyNeedle string - asciiOnlyWord uint64 - asciiOnlyFold uint64 - asciiOnly bool - asciiOnlyLong bool - asciiPair asciiPairProbe - asciiNeedle string - asciiFirstWord uint64 - asciiFirstFold uint64 - asciiTailWord uint64 - asciiTailFold uint64 - asciiTailMask uint64 - asciiVerifyTokens bool - asciiFixedPrefix int - asciiByteAnchor bool - asciiStaticAnchor bool - asciiStaticAt int - asciiStaticKind uint8 - asciiStaticByte byte - asciiRun bool - asciiRunKind uint8 - asciiRunByte byte - unicodeAnchor tripleFilter - unicodeAt int - unicodePairs [8]unicodePairAnchor - unicodePairN uint8 - singleTokens []uint32 + asciiProbe asciiProbe + asciiOnlyProbe asciiProbe + // singlePayload is the literal for the all-ASCII route. That route is + // disabled for Unicode patterns, where this otherwise unused string instead + // holds the packed raw terminal confirmation for the N=1 VBMI transition. + singlePayload string + asciiOnlyWord uint64 + asciiOnlyFold uint64 + asciiOnly bool + asciiOnlyLong bool + asciiPair asciiPairProbe + asciiNeedle string + asciiFirstWord uint64 + asciiFirstFold uint64 + asciiTailWord uint64 + asciiTailFold uint64 + asciiTailMask uint64 + asciiVerifyTokens bool + asciiFixedPrefix int + asciiByteAnchor bool + asciiStaticAnchor bool + asciiStaticAt int + asciiStaticKind uint8 + asciiStaticByte byte + asciiRun bool + asciiRunKind uint8 + asciiRunByte byte + unicodeAnchor tripleFilter + unicodeAt int + unicodePairs [8]unicodePairAnchor + unicodePairN uint8 + singleTokens []uint32 + // rawByteMulti is the fixed, tagged interior-pair screen used only by + // eligible multi-pattern enumeration. It is compiled into the plan with the + // raw transition map; it never depends on a caller's haystack or history. + rawByteMulti rawByteMultiAnchorFilter + rawByteOrigin rawByteOriginGate runes map[rune]uint32 opaqueContinuation bool @@ -81,8 +89,11 @@ type searchPlan struct { dense []uint32 stride int - empty int - maxUnits int + empty int + maxUnits int + // maxBytes bounds the source bytes consumed by any simple-fold spelling + // of a compiled pattern. Boundary windows use it to preserve cross-run matches. + maxBytes int patternCount int } @@ -105,8 +116,16 @@ type rootFilter struct { } const ( - pairShuftiGroups = 2 - pairShuftiSlots = 8 + pairShuftiGroups = 2 + pairShuftiSlots = 8 + asciiTripleMinBytes = 64 + + // A rolling exceptional-byte budget keeps a sparse prefix from admitting a + // later dense region. The partitioner checks the same bounded neighborhood + // as its entry guard while it discovers subsequent spans. + asciiPartitionSampleBytes = 1024 + asciiPartitionMaxHigh = 16 + asciiPartitionLookaheadBytes = asciiPartitionSampleBytes * asciiPartitionMaxHigh ) // pairShuftiGroup stores four nibble-to-slot tables. The slot bits identify @@ -885,9 +904,15 @@ func newSearchPlan(patterns []string) *searchPlan { continue } - state, units := 0, 0 + state, units, maxBytes := 0, 0, 0 for at := 0; at < len(pattern); { token, size := p.patternToken(pattern, at, &nextToken) + r, _ := utf8.DecodeRuneInString(pattern[at:]) + unitBytes := size + if r != utf8.RuneError || size != 1 { + unitBytes = maxFoldRuneWidth(r) + } + maxBytes += unitBytes next, ok := p.nodes[state].edges[token] if !ok { next = len(p.nodes) @@ -912,6 +937,9 @@ func newSearchPlan(patterns []string) *searchPlan { if units > p.maxUnits { p.maxUnits = units } + if maxBytes > p.maxBytes { + p.maxBytes = maxBytes + } } p.finish(nextToken) @@ -922,9 +950,24 @@ func newSearchPlan(patterns []string) *searchPlan { p.makeASCIIAnchor(patterns[0]) p.makeUnicodeAnchor(patterns[0]) } + p.makeRawByteTokenPlan(patterns) return p } +// maxFoldRuneWidth returns the widest UTF-8 encoding in r's simple-fold orbit. +func maxFoldRuneWidth(r rune) int { + maxWidth := 1 + for member := r; ; member = unicode.SimpleFold(member) { + if width := utf8.RuneLen(member); width > maxWidth { + maxWidth = width + } + if unicode.SimpleFold(member) == r { + break + } + } + return maxWidth +} + // patternToken emits one token for a pattern unit and advances at by its // source width. A malformed pattern byte is an opaque unit, just as it is in a // haystack scan. @@ -1206,7 +1249,7 @@ func (p *searchPlan) makeASCIIOnlyProbe(pattern string) { p.asciiOnlyWord |= uint64(value) << (8 * at) } } - p.asciiOnlyNeedle = pattern + p.singlePayload = pattern p.asciiOnly = true } @@ -1467,6 +1510,14 @@ func (p *searchPlan) makeUnicodePairAnchor(pattern string) { func (p *searchPlan) makeUnicodeAnchor(pattern string) { p.makeUnicodePairAnchor(pattern) + if !p.asciiOnly && p.unicodePairN != 0 && p.unicodePairs[0].pairPair.valid != 0 { + anchor := p.unicodePairs[0] + if confirm := makeUnicodePairConfirm(pattern, anchor.at, anchor.confirmAt); confirm.valid() { + p.singlePayload = string(confirm) + } else if confirm := makeUnicodePairVariableConfirm(pattern, anchor.at); confirm.valid() { + p.singlePayload = string(confirm) + } + } forms, widths := patternRawForms(pattern) offset, fixedPrefix := 0, true var best tripleFilter @@ -1901,6 +1952,12 @@ func (p *searchPlan) haystackToken(s string, at int) (uint32, int) { } r, size := utf8.DecodeRuneInString(s[at:]) if r == utf8.RuneError && size == 1 { + // An eligible raw-byte plan has no opaque pattern bytes. Its opaque + // storage holds direct two-byte tokens instead, so malformed input must + // remain the ordinary zero-token reset. + if p.hasRawByteTokenPlan() { + return 0, 1 + } return p.opaque[byteValue], 1 } return p.runes[r], size @@ -2197,8 +2254,55 @@ func pairFilterAt(haystack string, at int, filter *rootFilter) bool { return false } -func (p *searchPlan) findUnicodePairAnchor(haystack string, anchor *unicodePairAnchor) (Match, bool) { +// findUnicodePairConfirm keeps the exact N=1 raw confirmation in the VBMI +// transition for full vector blocks. The scalar tail remains bounded and uses +// the same compiled raw forms, while unavailable vector hosts retain the +// decoded executor below. +func (p *searchPlan) unicodePairConfirm() unicodePairConfirm { + if p.asciiOnly { + return "" + } + return unicodePairConfirm(p.singlePayload) +} + +func (p *searchPlan) findUnicodePairConfirm(haystack string, anchor *unicodePairAnchor) (Match, int, bool) { + confirm := p.unicodePairConfirm() + if len(haystack) < confirm.minLength() { + return Match{}, 0, false + } + + at := anchor.at + if lastStart := len(haystack) - confirm.maxLength(); lastStart >= 0 { + full := (lastStart + 1) &^ 63 + if full != 0 { + skipped, width := pairPairConfirmBytes(haystack, at, full, &anchor.pairPair, confirm) + if skipped < full { + return Match{Pattern: 0, Start: at + skipped - anchor.at}, width, true + } + at += full + } + } + + lastAnchor := len(haystack) - confirm.minLength() + anchor.at + for at <= lastAnchor { + at += pairPairSkipBytes(haystack, at, &anchor.pairPair) + if at > lastAnchor { + break + } + start := at - anchor.at + if width, ok := confirm.matchWidthAt(haystack, start); ok { + return Match{Pattern: 0, Start: start}, width, true + } + at++ + } + return Match{}, 0, false +} + +func (p *searchPlan) findUnicodePairAnchor(haystack string, anchor *unicodePairAnchor) (Match, int, bool) { if anchor.pairPair.valid != 0 { + if p.unicodePairConfirm().valid() && unicodePairConfirmVectorEnabled() { + return p.findUnicodePairConfirm(haystack, anchor) + } for at := 0; at+int(anchor.pairPair.offset)+1 < len(haystack); { at += pairPairSkipBytes(haystack, at, &anchor.pairPair) if at+int(anchor.pairPair.offset)+1 >= len(haystack) { @@ -2206,11 +2310,11 @@ func (p *searchPlan) findUnicodePairAnchor(haystack string, anchor *unicodePairA } start := at - anchor.at if start >= 0 && p.matchesSingleAt(haystack, start) { - return Match{Pattern: 0, Start: start}, true + return Match{Pattern: 0, Start: start}, 0, true } at++ } - return Match{}, false + return Match{}, 0, false } for at := 0; at+1 < len(haystack); { at += filterSkipBytes(haystack, at, &anchor.filter) @@ -2219,11 +2323,11 @@ func (p *searchPlan) findUnicodePairAnchor(haystack string, anchor *unicodePairA } start := at - anchor.at if start >= 0 && pairFilterAt(haystack, start+anchor.confirmAt, &anchor.confirm) && p.matchesSingleAt(haystack, start) { - return Match{Pattern: 0, Start: start}, true + return Match{Pattern: 0, Start: start}, 0, true } at++ } - return Match{}, false + return Match{}, 0, false } func (p *searchPlan) findUnicodeAnchor(haystack string) (Match, bool) { @@ -2241,56 +2345,77 @@ func (p *searchPlan) findUnicodeAnchor(haystack string) (Match, bool) { return Match{}, false } +func withZeroWidth(match Match, ok bool) (Match, int, bool) { + return match, 0, ok +} + func (p *searchPlan) find(haystack string) (Match, bool) { + match, _, ok := p.findWithWidth(haystack) + return match, ok +} + +// findWithWidth is the package's one search decision tree. Most routes return +// zero width; an exact raw confirmation returns the source width it has already +// proved so Matcher.Each does not decode the same match again. +func (p *searchPlan) findWithWidth(haystack string) (Match, int, bool) { if p.maxUnits == 0 { if p.empty >= 0 { - return Match{Pattern: p.empty}, true + return Match{Pattern: p.empty}, 0, true } - return Match{}, false + return Match{}, 0, false } if p.opaqueContinuation { - return p.findUnfiltered(haystack) + return withZeroWidth(p.findUnfiltered(haystack)) } if p.asciiRun { - return p.findASCIIRun(haystack) + return withZeroWidth(p.findASCIIRun(haystack)) } if p.asciiPair.usable() && len(haystack) >= len(p.asciiNeedle) && p.asciiFixedAt(haystack, 0) { - return Match{Pattern: 0}, true + return Match{Pattern: 0}, 0, true } if p.asciiPairVBMIDisplaced() && len(haystack) >= 4096 && asciiPairVBMIEnabled() { - return p.findASCIIPairAnchor(haystack) + return withZeroWidth(p.findASCIIPairAnchor(haystack)) } if !p.asciiPairVBMIDisplaced() && p.asciiPair.usable() && p.asciiPairPromising() { - return p.findASCIIPairAnchor(haystack) + return withZeroWidth(p.findASCIIPairAnchor(haystack)) } if p.asciiStaticAnchor && len(haystack) >= 4096 { - return p.findASCIIByteAnchor(haystack, p.asciiStaticAt, p.asciiStaticKind, p.asciiStaticByte) + return withZeroWidth(p.findASCIIByteAnchor(haystack, p.asciiStaticAt, p.asciiStaticKind, p.asciiStaticByte)) } if p.asciiByteAnchor { if anchorAt, kind, needle, ok := p.chooseASCIIByteAnchor(haystack); ok { - return p.findASCIIByteAnchor(haystack, anchorAt, kind, needle) + return withZeroWidth(p.findASCIIByteAnchor(haystack, anchorAt, kind, needle)) } } if !p.asciiPairVBMIDisplaced() && p.asciiPair.usable() && len(haystack) >= 4096 && p.asciiPairSparse(haystack) { - return p.findASCIIPairAnchor(haystack) + return withZeroWidth(p.findASCIIPairAnchor(haystack)) } if p.asciiProbe.usable() { - return p.findASCIIAnchor(haystack) + return withZeroWidth(p.findASCIIAnchor(haystack)) } // k and s have width-changing Unicode orbit members, so their patterns do // not enter the fixed ASCII probe above. The integrated high-byte check lets // a short or structured ASCII haystack use the same vector transition in one // pass; any high byte falls through to the full Unicode plan unchanged. if p.asciiOnly && (len(haystack) <= 4096 || p.asciiOnlyLong) { - if match, ok, handled := p.findASCIIOnlyAnchor(haystack, p.asciiOnlyNeedle); handled { - return match, ok + if match, ok, handled := p.findASCIIOnlyAnchor(haystack, p.singlePayload); handled { + return match, 0, ok } } + // The tagged multi-anchor filter is one plan-owned raw transition scan for + // both Find and Each. Its exact replay decides the result, so Find can stop + // at the first completed leftmost candidate without selecting a second engine. + if p.rawByteMulti.usable() { + if len(haystack) >= 4096 && p.rawByteOrigin.usable() { + return withZeroWidth(p.findRawByteOrigin(haystack)) + } + return withZeroWidth(p.findRawByteFixedAnchored(haystack)) + } if anchor := p.chooseUnicodePairAnchor(haystack); anchor != nil { return p.findUnicodePairAnchor(haystack, anchor) } if p.unicodeAnchor.n == 1 { - return p.findUnicodeAnchor(haystack) + return withZeroWidth(p.findUnicodeAnchor(haystack)) } // A partial root triple set cannot skip a general UTF-8 stream because a // non-ASCII-only root may occur later. On AVX-512 BW, the high-byte scan @@ -2298,29 +2423,248 @@ func (p *searchPlan) find(haystack string) (Match, bool) { // the separately covered ASCII roots for the bounded Shufti transition. It // still advances this one compiled plan at every survivor; it is a block // transition, not a second matcher. - const asciiTripleMinBytes = 64 if p.asciiPairAnchors.usable() && runtimeVectorBits() == 512 && len(haystack) >= asciiTripleMinBytes && rootSkipASCII(haystack, 0, rootExact, 0) == len(haystack) { - return p.findASCIIPairAnchored(haystack) + return withZeroWidth(p.findASCIIPairAnchored(haystack)) } if p.patternCount > 1 && p.rootKind == rootGeneric && p.asciiTriplesComplete && p.asciiTriples.shufti.usable() && runtimeVectorBits() == 512 && len(haystack) >= asciiTripleMinBytes && rootSkipASCII(haystack, 0, rootExact, 0) == len(haystack) { - return p.findASCIITripleFiltered(haystack) + return withZeroWidth(p.findASCIITripleFiltered(haystack)) } if p.triplesComplete && p.triples.usable() && (p.patternCount == 1 || p.rootKind == rootGeneric) { - return p.findFiltered(haystack) + return withZeroWidth(p.findFiltered(haystack)) } if p.rootKind == rootGeneric && p.filter.usable() { - return p.findFiltered(haystack) + return withZeroWidth(p.findFiltered(haystack)) } - return p.findUnfiltered(haystack) + return withZeroWidth(p.findUnfiltered(haystack)) +} + +// asciiPartitionWindowWorthwhile keeps a widened window from dominating short +// haystacks with unusually wide compiled patterns. +func asciiPartitionWindowWorthwhile(length, maxBytes int) bool { + // A widened window spends up to maxBytes on either side of an exceptional + // span. Keep at least three quarters of a sufficiently long haystack + // available for ASCII-run work; short inputs and very wide compiled patterns + // otherwise turn the partition into extra work. + return length >= 2*asciiPartitionSampleBytes && maxBytes > 0 && maxBytes <= length/8 } // findUnfiltered advances the decoded plan without raw byte filters. It is the // boundary-safe path for plans containing opaque UTF-8 continuation bytes. func (p *searchPlan) findUnfiltered(haystack string) (Match, bool) { + if p.asciiPartitionUsable() && asciiPartitionWindowWorthwhile(len(haystack), p.maxBytes) && !asciiPartitionTailBoundary(haystack) { + firstHigh := rootSkipASCII(haystack, 0, rootExact, 0) + if firstHigh < len(haystack) && asciiPartitionSparseEnough(haystack, firstHigh) { + return p.findPartitionedASCII(haystack, firstHigh) + } + } + return p.findUnfilteredDecodedLegacy(haystack) +} + +// asciiPartitionStats is an optional diagnostic view of the partition route. +// It is populated only by focused package benchmarks; normal searches pass nil +// and retain the same hot path without counters. +type asciiPartitionStats struct { + highBytes int + firstExceptional int + asciiCandidateBytes int + decodedWindowBytes int + decodedWindows int + fallbackEntries int +} + +func (p *searchPlan) findUnfilteredWithStats(haystack string, stats *asciiPartitionStats) (Match, bool) { + if stats != nil { + stats.firstExceptional = -1 + } + if p.asciiPartitionUsable() && asciiPartitionWindowWorthwhile(len(haystack), p.maxBytes) && !asciiPartitionTailBoundary(haystack) { + firstHigh := rootSkipASCII(haystack, 0, rootExact, 0) + if firstHigh < len(haystack) && asciiPartitionSparseEnough(haystack, firstHigh) { + if stats != nil { + stats.firstExceptional = firstHigh + return p.findPartitionedASCIIWithStats(haystack, firstHigh, stats) + } + return p.findPartitionedASCII(haystack, firstHigh) + } + } + if stats != nil { + stats.fallbackEntries++ + for at := 0; at < len(haystack); at++ { + if haystack[at] >= utf8.RuneSelf { + stats.highBytes++ + if stats.firstExceptional < 0 { + stats.firstExceptional = at + } + } + } + } + return p.findUnfilteredDecodedLegacy(haystack) +} + +// asciiPartitionTailBoundary keeps the old decoded executor for dense input +// and for a final boundary with no block-sized run after it. Earlier runs are +// still eligible when the tail is clean, while the check itself is bounded by +// the existing ASCII block threshold. +func asciiPartitionTailBoundary(haystack string) bool { + if len(haystack) < asciiTripleMinBytes { + return true + } + start := len(haystack) - asciiTripleMinBytes + for at := start; at < len(haystack); at++ { + if haystack[at] >= utf8.RuneSelf || haystack[at] == 0 { + return true + } + } + return false +} + +// asciiPartitionSparseEnough rejects exceptional-byte densities for which the +// boundary work and repeated decoded transitions cost more than the legacy +// executor. The samples are deliberately capped and spread through the input: +// sparse inputs retain the vector ASCII gaps, while a later dense region is +// rejected before the first partitioned window is spent on it. +func asciiPartitionSparseEnough(haystack string, firstExceptional int) bool { + sparseSample := func(start, end int) bool { + high := 0 + for at := start; at < end; { + at += rootSkipASCII(haystack[:end], at, rootExact, 0) + if at >= end { + break + } + if haystack[at] == 0 { + return false + } + high++ + if high >= asciiPartitionMaxHigh { + return false + } + at++ + } + return true + } + + end := firstExceptional + asciiPartitionSampleBytes + if end > len(haystack) { + end = len(haystack) + } + if !sparseSample(firstExceptional, end) { + return false + } + if len(haystack)-firstExceptional <= asciiPartitionSampleBytes { + return true + } + + // A bounded set of fixed-fraction samples catches a dense suffix or middle + // without turning admission into a second full haystack scan. Keep samples + // disjoint from the first window and clamp them at the input boundary. + for _, start := range [...]int{len(haystack) / 4, len(haystack) / 2, len(haystack) - asciiPartitionSampleBytes} { + if start < end { + continue + } + if !sparseSample(start, start+asciiPartitionSampleBytes) { + return false + } + } + return true +} + +// findUnfilteredDecodedLegacy retains the original decoded prefix and +// fallback shape for plans that cannot profit from ASCII-run re-entry. Keeping +// this owner separate prevents the partition state and its boundary checks +// from changing ordinary fallback work. +func (p *searchPlan) findUnfilteredDecodedLegacy(haystack string) (Match, bool) { + state, unit := 0, 0 + bestUnitStart := -1 + best := Match{Pattern: -1, Start: -1} + if p.empty >= 0 { + // An empty pattern is a candidate at start zero, not an immediate + // answer: a lower-index non-empty pattern may also start at zero. + bestUnitStart = 0 + best = Match{Pattern: p.empty, Start: 0} + } + + // Common text stays in this no-allocation path. Because each preceding + // unit is one byte, a terminal's source start is direct arithmetic rather + // than a lookup in the variable-width offset ring used after the first + // non-ASCII byte. + at := 0 + for at < len(haystack) && haystack[at] < utf8.RuneSelf { + // A root-to-root block cannot emit a non-empty terminal. Advance over + // sixteen such bytes at once; every other block remains on the exact + // same transition path below. + if state == 0 { + if p.rootKind != rootGeneric { + for at < len(haystack) { + skipped := rootSkipASCII(haystack, at, p.rootKind, p.rootNeedle) + if p.pairKind != rootGeneric { + skipped = pairSkipASCII(haystack, at, p.rootKind, p.rootNeedle, p.pairKind, p.pairNeedle) + } + if skipped == 0 { + break + } + if bestUnitStart >= 0 && unit+skipped-1 >= bestUnitStart+p.maxUnits-1 { + return best, true + } + at += skipped + unit += skipped + } + } else { + for at+16 <= len(haystack) { + block := haystack[at : at+16] + if p.rootByte[block[0]]|p.rootByte[block[1]]|p.rootByte[block[2]]|p.rootByte[block[3]]| + p.rootByte[block[4]]|p.rootByte[block[5]]|p.rootByte[block[6]]|p.rootByte[block[7]]| + p.rootByte[block[8]]|p.rootByte[block[9]]|p.rootByte[block[10]]|p.rootByte[block[11]]| + p.rootByte[block[12]]|p.rootByte[block[13]]|p.rootByte[block[14]]|p.rootByte[block[15]] != 0 { + break + } + if bestUnitStart >= 0 && unit+15 >= bestUnitStart+p.maxUnits-1 { + return best, true + } + at += len(block) + unit += len(block) + } + } + if at == len(haystack) || haystack[at] >= utf8.RuneSelf { + break + } + } + state = p.advance(state, p.ascii[haystack[at]]) + if output := p.nodes[state].output; output.pattern >= 0 { + startUnit := unit - output.units + 1 + if bestUnitStart < 0 || startUnit < bestUnitStart || + startUnit == bestUnitStart && output.pattern < best.Pattern { + bestUnitStart = startUnit + best = Match{Pattern: output.pattern, Start: startUnit} + } + } + if bestUnitStart >= 0 && unit >= bestUnitStart+p.maxUnits-1 { + return best, true + } + at++ + unit++ + } + if at == len(haystack) { + if bestUnitStart < 0 { + return Match{}, false + } + return best, true + } + + var inlineStarts [256]int + starts := inlineStarts[:] + if p.maxUnits > len(starts) { + starts = make([]int, p.maxUnits) + } + return p.findNonASCIIDecoded(haystack, at, unit, state, bestUnitStart, best, starts) +} + +// findUnfilteredWithStarts is the decoded executor used for a bounded window. +// A caller can provide its offset ring so each window reuses the same stack +// storage rather than allocating a new ring. +func (p *searchPlan) findUnfilteredWithStarts(haystack string, starts []int) (Match, bool) { state, unit := 0, 0 bestUnitStart := -1 best := Match{Pattern: -1, Start: -1} @@ -2397,7 +2741,14 @@ func (p *searchPlan) findUnfiltered(haystack string) (Match, bool) { } return best, true } - return p.findNonASCII(haystack, at, unit, state, bestUnitStart, best) + if starts == nil { + var inlineStarts [256]int + starts = inlineStarts[:] + if p.maxUnits > len(starts) { + starts = make([]int, p.maxUnits) + } + } + return p.findNonASCII(haystack, at, unit, state, bestUnitStart, best, starts) } // findASCIITripleFiltered is the all-ASCII specialization of the shared plan. @@ -2449,6 +2800,70 @@ func (p *searchPlan) findASCIITripleFiltered(haystack string) (Match, bool) { return best, true } +// tripleSkipASCIIRegion scans candidate starts in [start,end). The byte scout +// may inspect the two following bytes needed by overlapping triple loads, but +// the returned skip is clamped to the known-ASCII region. The decoded boundary +// window owns starts whose source crosses the following exceptional span. +func tripleSkipASCIIRegion(s string, start, end int, filter *tripleFilter) int { + if start >= end { + return 0 + } + scanEnd := end + 2 + if scanEnd > len(s) { + scanEnd = len(s) + } + skipped := tripleSkipBytes(s[start:scanEnd], 0, filter) + if limit := end - start; skipped > limit { + return limit + } + return skipped +} + +// findASCIITripleFilteredRange is the bounded form used for a maximal ASCII +// run. Its vector scout may read two bytes beyond end from the original +// haystack, but it never advances a candidate beyond end; a decoded window +// handles matches whose source crosses the following exceptional span. +func (p *searchPlan) findASCIITripleFilteredRange(haystack string, start, end int) (Match, bool) { + var inlineStarts [256]int + starts := inlineStarts[:] + if p.maxUnits > len(starts) { + starts = make([]int, p.maxUnits) + } + + state, history := 0, 0 + best := Match{Pattern: -1, Start: -1} + for at := start; at < end; { + if state == 0 { + if best.Pattern >= 0 && at > best.Start { + return best, true + } + history = 0 + skipped := tripleSkipASCIIRegion(haystack, at, end, &p.asciiTriples) + at += skipped + if at == end { + break + } + } + + starts[history%len(starts)] = at + token, size := p.haystackToken(haystack, at) + state = p.advance(state, token) + history++ + if output := p.nodes[state].output; output.pattern >= 0 { + startAt := starts[(history-output.units)%len(starts)] + if best.Pattern < 0 || startAt < best.Start || + startAt == best.Start && output.pattern < best.Pattern { + best = Match{Pattern: output.pattern, Start: startAt} + } + } + at += size + } + if best.Pattern < 0 { + return Match{}, false + } + return best, true +} + // replayASCIIAnchorStart feeds a bounded candidate window back through the // shared compiled plan. Filtering never confirms a pattern directly: the // plan's propagated outputs select both the terminal and its lowest-ID tie. @@ -2537,6 +2952,7 @@ func (p *searchPlan) findFiltered(haystack string) (Match, bool) { if p.empty >= 0 { best = Match{Pattern: p.empty, Start: 0} } + raw := p.hasRawByteTokenPlan() for at := 0; at < len(haystack); { if state == 0 { // Once no prefix is live, a previously found start cannot be @@ -2566,8 +2982,39 @@ func (p *searchPlan) findFiltered(haystack string) (Match, bool) { } starts[history%len(starts)] = at - token, size := p.haystackToken(haystack, at) - state = p.advance(state, token) + size := 0 + if raw { + // Keep the raw classification in this loop so the source-byte loads + // and dense transition stay in one generated body. Wider and malformed + // input falls through to the complete decoded transition below. + value := haystack[at] + if value < utf8.RuneSelf { + token := p.ascii[value] + if token == 0 { + state = 0 + } else { + state = int(p.dense[state*p.stride+int(token)]) + } + size = 1 + } else if value >= 0xc2 && value <= 0xdf && at+1 < len(haystack) { + trail := haystack[at+1] + if trail >= 0x80 && trail < 0xc0 { + row := p.opaque[value] + if row == 0 { + state = 0 + } else if token := p.opaque[(int(row)-1)*rawByteTrailClasses+int(trail-0x80)]; token == 0 { + state = 0 + } else { + state = int(p.dense[state*p.stride+int(token)]) + } + size = 2 + } + } + } + if size == 0 { + token, decodedSize := p.haystackToken(haystack, at) + state, size = p.advance(state, token), decodedSize + } history++ if output := p.nodes[state].output; output.pattern >= 0 { start := starts[(history-output.units)%len(starts)] @@ -2584,15 +3031,243 @@ func (p *searchPlan) findFiltered(haystack string) (Match, bool) { return best, true } -// findNonASCII resumes the plan at its first non-ASCII byte. The ASCII prefix -// has one source byte per unit, so its still-live starts can be reconstructed -// into the offset ring without a second traversal of the haystack. -func (p *searchPlan) findNonASCII(haystack string, at, unit, state, bestUnitStart int, best Match) (Match, bool) { +func (p *searchPlan) asciiPartitionUsable() bool { + if p.empty >= 0 || p.opaqueContinuation || p.rootKind != rootGeneric || p.patternCount <= 1 || + !p.asciiTriplesComplete || !p.asciiTriples.shufti.usable() { + return false + } + return runtimeVectorBits() == 512 +} + +// findASCIIRegion runs the strongest existing byte candidate transition that +// is sound on a known-ASCII region. The caller has already separated all bytes +// at or above UTF-8's RuneSelf, so the all-ASCII routes do not need to prove +// that property again. +func (p *searchPlan) findASCIIRegion(haystack string, start, end int, starts []int) (Match, bool) { + if end-start >= asciiTripleMinBytes { + return p.findASCIITripleFilteredRange(haystack, start, end) + } + match, ok := p.findUnfilteredWithStarts(haystack[start:end], starts) + if ok { + match.Start += start + } + return match, ok +} + +// findPartitionedASCII resumes after the first high byte. It visits each +// maximal ASCII run with the existing candidate transition and decodes only a +// coalesced window around exceptional spans. The ASCII transition stops at the +// exceptional byte, so it can confirm matches that finish before that byte; +// the decoded window owns starts whose source crosses the span. +func (p *searchPlan) findPartitionedASCII(haystack string, firstHigh int) (Match, bool) { + return p.findPartitionedASCIIWithStats(haystack, firstHigh, nil) +} + +func (p *searchPlan) findPartitionedASCIIWithStats(haystack string, firstHigh int, stats *asciiPartitionStats) (Match, bool) { + maxBytes := p.maxBytes + if maxBytes < 1 || firstHigh >= len(haystack) { + return Match{}, false + } + var inlineStarts [256]int starts := inlineStarts[:] if p.maxUnits > len(starts) { starts = make([]int, p.maxUnits) } + + var recentHigh [asciiPartitionMaxHigh]int + recentHighCount := 0 + checkExceptional := func(start, end int, recent [asciiPartitionMaxHigh]int, count int) ([asciiPartitionMaxHigh]int, int, bool) { + for at := start; at < end; at++ { + if haystack[at] == 0 { + return recent, count, false + } + if haystack[at] < utf8.RuneSelf { + continue + } + if count >= asciiPartitionMaxHigh-1 && + at-recent[(count-(asciiPartitionMaxHigh-1))%asciiPartitionMaxHigh] < asciiPartitionSampleBytes { + return recent, count, false + } + recent[count%asciiPartitionMaxHigh] = at + count++ + } + // Malformed bytes have no stable decoded window to amortize. Keep their + // established opaque-byte executor rather than paying one transition per + // isolated high byte. The density checks above run first so a contiguous + // exceptional suffix is rejected without validating it in full. + return recent, count, utf8.ValidString(haystack[start:end]) + } + recordExceptional := func(start, end int) bool { + var ok bool + recentHigh, recentHighCount, ok = checkExceptional(start, end, recentHigh, recentHighCount) + return ok + } + + cursor := 0 + fallback := func() (Match, bool) { + if stats != nil { + stats.fallbackEntries++ + } + match, ok := p.findUnfilteredDecodedLegacy(haystack[cursor:]) + if ok { + match.Start += cursor + } + return match, ok + } + spanStart := firstHigh + pendingMatch := Match{} + pendingOK := false + for { + spanEnd := spanStart + for spanEnd < len(haystack) && (haystack[spanEnd] >= utf8.RuneSelf || haystack[spanEnd] == 0) { + spanEnd++ + } + if !recordExceptional(spanStart, spanEnd) { + return fallback() + } + if stats != nil { + for at := spanStart; at < spanEnd; at++ { + if haystack[at] >= utf8.RuneSelf { + stats.highBytes++ + } + } + } + windowStart := spanStart - maxBytes + if windowStart < 0 { + windowStart = 0 + } + windowEnd := spanEnd + maxBytes + if windowEnd > len(haystack) { + windowEnd = len(haystack) + } + lastHighEnd := spanEnd + + // Coalesce exceptional spans whose widened windows touch. This leaves + // one decoded transition for a cluster rather than restarting it at + // every high byte. + nextStart := -1 + for at := spanEnd; at < len(haystack); { + at += rootSkipASCII(haystack, at, rootExact, 0) + if at == len(haystack) { + break + } + nextSpanEnd := at + for nextSpanEnd < len(haystack) && (haystack[nextSpanEnd] >= utf8.RuneSelf || haystack[nextSpanEnd] == 0) { + nextSpanEnd++ + } + nextWindowStart := at - maxBytes + if nextWindowStart < 0 { + nextWindowStart = 0 + } + nextWindowEnd := nextSpanEnd + maxBytes + if nextWindowEnd > len(haystack) { + nextWindowEnd = len(haystack) + } + // Probe nearby next spans before spending the current group's window. A + // dense or malformed span must not make us partition work and then + // restart the legacy decoder from the same safe cursor. For a distant + // span, process this group first so a later fallback can resume after + // its widened window instead of rescanning this ASCII gap. + if nextWindowStart > windowEnd && at-spanStart > asciiPartitionLookaheadBytes { + nextStart = at + break + } + probeHigh, probeCount, ok := checkExceptional(at, nextSpanEnd, recentHigh, recentHighCount) + if !ok { + return fallback() + } + if nextWindowStart > windowEnd { + nextStart = at + break + } + recentHigh, recentHighCount = probeHigh, probeCount + if stats != nil { + for high := at; high < nextSpanEnd; high++ { + if haystack[high] >= utf8.RuneSelf { + stats.highBytes++ + } + } + } + if nextWindowEnd > windowEnd { + windowEnd = nextWindowEnd + } + lastHighEnd = nextSpanEnd + at = nextSpanEnd + } + + asciiMatch := pendingMatch + asciiOK := pendingOK + pendingOK = false + if cursor < spanStart { + if stats != nil { + stats.asciiCandidateBytes += spanStart - cursor + } + regionMatch, regionOK := p.findASCIIRegion(haystack, cursor, spanStart, starts) + if regionOK && (!asciiOK || regionMatch.Start < asciiMatch.Start || + regionMatch.Start == asciiMatch.Start && regionMatch.Pattern < asciiMatch.Pattern) { + asciiMatch, asciiOK = regionMatch, true + } + } + if asciiOK && asciiMatch.Start < windowStart { + return asciiMatch, true + } + if stats != nil { + stats.decodedWindowBytes += windowEnd - windowStart + stats.decodedWindows++ + } + windowMatch, windowOK := p.findUnfilteredWithStarts(haystack[windowStart:windowEnd], starts) + if windowOK { + windowMatch.Start += windowStart + } + if asciiOK && (!windowOK || asciiMatch.Start < windowMatch.Start || + asciiMatch.Start == windowMatch.Start && asciiMatch.Pattern < windowMatch.Pattern) { + return asciiMatch, true + } + if windowOK { + return windowMatch, true + } + + if nextStart < 0 { + if lastHighEnd < len(haystack) { + if stats != nil { + stats.asciiCandidateBytes += len(haystack) - lastHighEnd + } + return p.findASCIIRegion(haystack, lastHighEnd, len(haystack), starts) + } + return Match{}, false + } + + // The next group starts after this group's widened window. Search the + // ASCII gap before its decoded window; starts in that window's overlap + // are checked by the next iteration against cross-span matches. + nextWindowStart := nextStart - maxBytes + if nextWindowStart < 0 { + nextWindowStart = 0 + } + if lastHighEnd < nextStart { + if stats != nil { + stats.asciiCandidateBytes += nextStart - lastHighEnd + } + if match, ok := p.findASCIIRegion(haystack, lastHighEnd, nextStart, starts); ok { + if match.Start < nextWindowStart { + return match, true + } + pendingMatch, pendingOK = match, true + } + } + cursor = nextWindowStart + spanStart = nextStart + } +} + +// findNonASCII resumes the plan at its first non-ASCII byte. It retains the +// original decoded executor for bounded windows and short known-ASCII regions. +func (p *searchPlan) findNonASCII(haystack string, at, unit, state, bestUnitStart int, best Match, starts []int) (Match, bool) { + return p.findNonASCIIDecoded(haystack, at, unit, state, bestUnitStart, best, starts) +} + +func (p *searchPlan) findNonASCIIDecoded(haystack string, at, unit, state, bestUnitStart int, best Match, starts []int) (Match, bool) { first := unit - p.maxUnits + 1 if first < 0 { first = 0 diff --git a/raw_byte.go b/raw_byte.go new file mode 100644 index 0000000..63045f3 --- /dev/null +++ b/raw_byte.go @@ -0,0 +1,824 @@ +package casei + +import ( + "math/bits" + "unicode" + "unicode/utf8" +) + +// A raw-byte token plan keeps the two-byte UTF-8 spellings needed by a small +// dense multi-pattern plan in the plan's already-reserved opaque-token array. +// The normal opaque table is unused for an eligible plan: it has no malformed +// pattern bytes. Reusing that storage makes the replacement transition +// allocation-free for a fresh Matcher as well as for a reused one. +const ( + rawByteMaxLeadRows = 2 + rawByteTrailClasses = 0x40 + rawByteTokenClasses = rawByteMaxLeadRows * rawByteTrailClasses + rawByteTransitionStride = utf8.RuneSelf + rawByteTokenClasses + rawByteMaxTransitionSize = 48 << 10 +) + +// rawByteTokenConfig maps the two-byte UTF-8 spellings in the existing fold +// token map to their dense token. ASCII already has p.ascii, so it needs no +// duplicate entries. A lead row is deliberately correlated with its following +// continuation byte; no independent byte masks can make a two-byte rune. +type rawByteTokenConfig struct { + leads [rawByteMaxLeadRows]byte + leadN uint8 + tokens [rawByteTokenClasses]uint32 +} + +// rawByteTokenConfigFor proves that every direct class is the same token the +// decoded path would select. The compact path is intentionally limited to the +// small plans for which its dense transition table remains cache-resident. +func (p *searchPlan) rawByteTokenConfigFor() (rawByteTokenConfig, bool) { + var config rawByteTokenConfig + if p.patternCount < 2 || p.dense == nil || + len(p.nodes) > rawByteMaxTransitionSize/(2*rawByteTransitionStride) || + len(p.dense) > rawByteMaxTransitionSize/4 { + return config, false + } + for _, token := range p.opaque { + if token != 0 { + return config, false + } + } + + var haveLead [256]bool + for r := range p.runes { + if r < utf8.RuneSelf { + continue + } + var encoded [utf8.UTFMax]byte + if utf8.EncodeRune(encoded[:], r) == 2 { + haveLead[encoded[0]] = true + } + } + for lead := range haveLead { + if !haveLead[lead] { + continue + } + if int(config.leadN) == len(config.leads) { + return rawByteTokenConfig{}, false + } + config.leads[config.leadN] = byte(lead) + config.leadN++ + } + if config.leadN == 0 { + return rawByteTokenConfig{}, false + } + + for r, token := range p.runes { + if r < utf8.RuneSelf { + continue + } + var encoded [utf8.UTFMax]byte + if utf8.EncodeRune(encoded[:], r) != 2 || encoded[1] < 0x80 || encoded[1] >= 0xc0 { + continue + } + row := -1 + for i := 0; i < int(config.leadN); i++ { + if config.leads[i] == encoded[0] { + row = i + break + } + } + if row < 0 { + return rawByteTokenConfig{}, false + } + class := row*rawByteTrailClasses + int(encoded[1]-0x80) + if prior := config.tokens[class]; prior != 0 && prior != token { + return rawByteTokenConfig{}, false + } + config.tokens[class] = token + } + return config, true +} + +// makeRawByteTokenPlan records a proven compact raw map during normal plan +// construction. singleTokens is otherwise used only by one-pattern plans; an +// empty, non-nil slice marks this multi-pattern plan while pointing at storage +// it already owns. No lazy publication, allocation, or caller history is +// involved. +func (p *searchPlan) makeRawByteTokenPlan(patterns []string) { + config, ok := p.rawByteTokenConfigFor() + if !ok { + return + } + copy(p.opaque[:rawByteTokenClasses], config.tokens[:]) + for row := 0; row < int(config.leadN); row++ { + p.opaque[config.leads[row]] = uint32(row + 1) + } + p.singleTokens = p.opaque[:0] + p.makeRawByteMultiAnchorFilter(patterns) + if p.rawByteMulti.usable() { + p.rawByteOrigin = rawByteOriginGateFor(patterns) + } +} + +func (p *searchPlan) hasRawByteTokenPlan() bool { + return p.patternCount > 1 && p.dense != nil && p.singleTokens != nil && len(p.singleTokens) == 0 +} + +func (p *searchPlan) rawByteAdvanceToken(state int, token uint32) int { + if token == 0 { + return 0 + } + return int(p.dense[state*p.stride+int(token)]) +} + +// rawByteAdvance consumes exactly one ASCII byte or one complete two-byte UTF-8 +// sequence. Unsupported widths and malformed encodings return ok=false so the +// decoded path retains its full Unicode and opaque-byte authority. +func (p *searchPlan) rawByteAdvance(haystack string, at, state int) (next, size int, ok bool) { + value := haystack[at] + if value < utf8.RuneSelf { + return p.rawByteAdvanceToken(state, p.ascii[value]), 1, true + } + if value < 0xc2 || value > 0xdf || at+1 == len(haystack) { + return 0, 0, false + } + trail := haystack[at+1] + if trail < 0x80 || trail >= 0xc0 { + return 0, 0, false + } + row := p.opaque[value] + if row == 0 { + // This valid two-byte rune is absent from every pattern orbit, so its + // decoded token is zero and the shared state machine resets. + return 0, 2, true + } + token := p.opaque[(int(row)-1)*rawByteTrailClasses+int(trail-0x80)] + return p.rawByteAdvanceToken(state, token), 2, true +} + +// rawByteMultiAnchorGroups is bounded by the eight tag bits carried through +// the VBMI tables. Limiting the projection is a plan property, not a workload +// admission rule: plans outside it keep the ordinary decoded enumeration. +const ( + rawByteMultiAnchorGroups = 8 + rawByteMultiAnchorForms = 4 + rawByteMultiAnchorStartOffsets = 4 + rawByteMultiAnchorConfirmGroups = 3 +) + +// rawByteMultiAnchorPairSet lists the exact two-byte spellings of one selected +// fold orbit. The vector tables retain only low-six-bit membership, so this +// exact representation removes aliases before the shared plan is replayed. +type rawByteMultiAnchorPairSet struct { + pairs [rawByteMultiAnchorForms]uint16 + n uint8 +} + +func (pairs rawByteMultiAnchorPairSet) matches(s string, at int) bool { + if at < 0 || at+1 >= len(s) { + return false + } + value := uint16(s[at]) | uint16(s[at+1])<<8 + for i := 0; i < int(pairs.n); i++ { + if pairs.pairs[i] == value { + return true + } + } + return false +} + +// rawByteMultiAnchor records one literal's three correlated interior UTF-8 +// pairs. starts includes every possible source-byte prefix width before the +// primary pair, so a width-changing fold before an anchor can only create a +// replayed extra candidate, never hide the true match. +type rawByteMultiAnchor struct { + primary, confirm, guard rawByteMultiAnchorPairSet + starts [rawByteMultiAnchorStartOffsets]uint8 + confirmOffset [rawByteMultiAnchorConfirmGroups]uint8 + guardOffset [rawByteMultiAnchorStartOffsets]uint8 + startN, confirmN, guardN uint8 +} + +// rawByteMultiAnchorFilter is the compact vector-facing representation of one +// tagged pair for every literal. A bit identifies the literal group. The first +// confirmation table for an offset retains that bit only when the same literal +// owns both pairs; the exact third pair is checked in Go before the shared raw +// transition replay. The first 512 bytes have a fixed table layout consumed by +// rawByteMultiAnchorSkip64. +type rawByteMultiAnchorFilter struct { + first, second [64]byte + confirmFirst [rawByteMultiAnchorConfirmGroups][64]byte + confirmSecond [rawByteMultiAnchorConfirmGroups][64]byte + confirmOffset [rawByteMultiAnchorConfirmGroups]uint8 + confirmN, maxConfirmOffset uint8 + maxOffset, valid uint8 + anchors [rawByteMultiAnchorGroups]rawByteMultiAnchor +} + +// rawByteOriginGate records an exact ASCII byte found in every rendering of +// every raw-filter literal. maxPrefix bounds its latest folded source offset; +// a Find start before the first byte minus that bound is impossible. +type rawByteOriginGate struct { + byte byte + maxPrefix uint16 + valid uint8 +} + +func (gate rawByteOriginGate) usable() bool { return gate.valid != 0 } + +func (filter *rawByteMultiAnchorFilter) usable() bool { + return filter != nil && filter.valid != 0 +} + +// tagDiverse reports whether the compiled tagged anchors can distinguish at +// least two literals before replay. A shared prefix whose primary, +// confirmation, guard, and source-width sets are identical for every tag pays +// the vector filter and then replays every pattern at the same survivor; it has +// no multi-pattern selectivity and must retain the ordinary Unicode route. +func (filter *rawByteMultiAnchorFilter) tagDiverse() bool { + var first rawByteMultiAnchor + haveFirst := false + for _, anchor := range filter.anchors { + if anchor.startN == 0 { + continue + } + if !haveFirst { + first, haveFirst = anchor, true + continue + } + if anchor != first { + return true + } + } + return false +} + +// rawByteOriginGateFor intersects fixed ASCII runes across the literals. A +// chosen rune encodes as the same byte in every simple-fold spelling. For each +// literal the earliest such occurrence minimizes its worst-case prefix; the +// global maximum is the safe Find lookback bound. +func rawByteOriginGateFor(patterns []string) rawByteOriginGate { + var common [utf8.RuneSelf]bool + for i := range common { + common[i] = true + } + var maxPrefix [utf8.RuneSelf]uint16 + for _, pattern := range patterns { + var seen [utf8.RuneSelf]bool + var localPrefix [utf8.RuneSelf]uint16 + prefix := 0 + for at := 0; at < len(pattern); { + r, size := utf8.DecodeRuneInString(pattern[at:]) + if r == utf8.RuneError && size == 1 { + return rawByteOriginGate{} + } + if r < utf8.RuneSelf && unicode.SimpleFold(r) == r { + value := byte(r) + if !seen[value] || prefix < int(localPrefix[value]) { + seen[value] = true + localPrefix[value] = uint16(prefix) + } + } + maxWidth := 0 + for member := r; ; member = unicode.SimpleFold(member) { + var encoded [utf8.UTFMax]byte + if width := utf8.EncodeRune(encoded[:], member); width > maxWidth { + maxWidth = width + } + if unicode.SimpleFold(member) == r { + break + } + } + prefix += maxWidth + if prefix > int(^uint16(0)) { + return rawByteOriginGate{} + } + at += size + } + for value := range common { + if !seen[value] { + common[value] = false + continue + } + if localPrefix[value] > maxPrefix[value] { + maxPrefix[value] = localPrefix[value] + } + } + } + + frequency := rawByteMultiAnchorFrequency(patterns) + best, bestScore := -1, uint16(^uint16(0)) + for value, present := range common { + if !present { + continue + } + score := frequency[value] + if best < 0 || score < bestScore || score == bestScore && + (maxPrefix[value] < maxPrefix[best] || maxPrefix[value] == maxPrefix[best] && value < best) { + best, bestScore = value, score + } + } + if best < 0 { + return rawByteOriginGate{} + } + return rawByteOriginGate{byte: byte(best), maxPrefix: maxPrefix[best], valid: 1} +} + +func rawByteMultiAnchorPairSetFor(r rune) (rawByteMultiAnchorPairSet, bool) { + var out rawByteMultiAnchorPairSet + for member := r; ; member = unicode.SimpleFold(member) { + var encoded [utf8.UTFMax]byte + if utf8.EncodeRune(encoded[:], member) != 2 { + return rawByteMultiAnchorPairSet{}, false + } + pair := uint16(encoded[0]) | uint16(encoded[1])<<8 + duplicate := false + for i := 0; i < int(out.n); i++ { + duplicate = duplicate || out.pairs[i] == pair + } + if !duplicate { + if int(out.n) == len(out.pairs) { + return rawByteMultiAnchorPairSet{}, false + } + out.pairs[out.n] = pair + out.n++ + } + if unicode.SimpleFold(member) == r { + break + } + } + return out, out.n != 0 +} + +// rawByteMultiAnchorPrefixWidths records the bounded set of possible byte +// widths before an anchor. The cross product is deliberately collapsed by +// width: it is only used to nominate replay starts, whose shared plan decides +// whether that spelling actually matches. +func rawByteMultiAnchorPrefixWidths(pattern string, end int, out *[rawByteMultiAnchorStartOffsets]uint8) (int, bool) { + out[0] = 0 + n := 1 + for at := 0; at < end; { + r, size := utf8.DecodeRuneInString(pattern[at:]) + if r == utf8.RuneError && size == 1 { + return 0, false + } + var next [rawByteMultiAnchorStartOffsets]uint8 + nextN := 0 + for member := r; ; member = unicode.SimpleFold(member) { + var encoded [utf8.UTFMax]byte + width := utf8.EncodeRune(encoded[:], member) + for i := 0; i < n; i++ { + value := int(out[i]) + width + if value > int(^uint8(0)) { + return 0, false + } + duplicate := false + for j := 0; j < nextN; j++ { + duplicate = duplicate || next[j] == uint8(value) + } + if !duplicate { + if nextN == len(next) { + return 0, false + } + next[nextN] = uint8(value) + nextN++ + } + } + if unicode.SimpleFold(member) == r { + break + } + } + *out = next + n = nextN + at += size + } + return n, true +} + +// rawByteMultiAnchorFrequency estimates selectivity only from the immutable +// literal set. It intentionally never samples a haystack, so plan selection +// cannot become benchmark- or caller-dependent. +func rawByteMultiAnchorFrequency(patterns []string) (out [256]uint16) { + for _, pattern := range patterns { + for at := 0; at < len(pattern); { + r, size := utf8.DecodeRuneInString(pattern[at:]) + if r == utf8.RuneError && size == 1 { + break + } + for member := r; ; member = unicode.SimpleFold(member) { + var encoded [utf8.UTFMax]byte + for _, value := range encoded[:utf8.EncodeRune(encoded[:], member)] { + if out[value] != ^uint16(0) { + out[value]++ + } + } + if unicode.SimpleFold(member) == r { + break + } + } + at += size + } + } + return out +} + +func rawByteMultiAnchorPairCost(pairs rawByteMultiAnchorPairSet, frequency *[256]uint16) uint64 { + var cost uint64 + for i := 0; i < int(pairs.n); i++ { + pair := pairs.pairs[i] + first, second := byte(pair), byte(pair>>8) + firstCost, secondCost := uint64(frequency[first]), uint64(frequency[second]) + if firstCost == 0 { + firstCost = 1 + } + if secondCost == 0 { + secondCost = 1 + } + cost += firstCost * secondCost + } + return cost +} + +type rawByteMultiAnchorCandidate struct { + anchor rawByteMultiAnchor + score uint64 + at int +} + +// rawByteMultiAnchorRelativeWidths records all possible byte displacements +// from start to end. Independent width choices may yield a crossed offset, but +// that only creates a scalar-guarded replay; it cannot remove the true one. +func rawByteMultiAnchorRelativeWidths(pattern string, start, end int, out *[rawByteMultiAnchorStartOffsets]uint8) (int, bool) { + return rawByteMultiAnchorPrefixWidths(pattern[start:end], end-start, out) +} + +type rawByteMultiAnchorUnit struct { + at int + pairs rawByteMultiAnchorPairSet +} + +// rawByteMultiAnchorCandidateFor chooses three width-stable two-byte interior +// pairs. Variable-width forms between pairs are represented by every bounded +// displacement; this is why the vector filter has three confirmation groups. +func rawByteMultiAnchorCandidateFor(pattern string, primary, confirm, guard rawByteMultiAnchorUnit, frequency *[256]uint16) (rawByteMultiAnchorCandidate, bool) { + if primary.at == 0 { + return rawByteMultiAnchorCandidate{}, false + } + var starts, guardOffsets [rawByteMultiAnchorStartOffsets]uint8 + var possibleConfirmOffsets [rawByteMultiAnchorStartOffsets]uint8 + startN, ok := rawByteMultiAnchorPrefixWidths(pattern, primary.at, &starts) + if !ok || startN == 0 { + return rawByteMultiAnchorCandidate{}, false + } + confirmN, ok := rawByteMultiAnchorRelativeWidths(pattern, primary.at, confirm.at, &possibleConfirmOffsets) + if !ok || confirmN == 0 || confirmN > rawByteMultiAnchorConfirmGroups { + return rawByteMultiAnchorCandidate{}, false + } + var confirmOffsets [rawByteMultiAnchorConfirmGroups]uint8 + copy(confirmOffsets[:], possibleConfirmOffsets[:confirmN]) + guardN, ok := rawByteMultiAnchorRelativeWidths(pattern, primary.at, guard.at, &guardOffsets) + if !ok || guardN == 0 { + return rawByteMultiAnchorCandidate{}, false + } + return rawByteMultiAnchorCandidate{ + anchor: rawByteMultiAnchor{ + primary: primary.pairs, + confirm: confirm.pairs, + guard: guard.pairs, + starts: starts, + confirmOffset: confirmOffsets, + guardOffset: guardOffsets, + startN: uint8(startN), + confirmN: uint8(confirmN), + guardN: uint8(guardN), + }, + score: rawByteMultiAnchorPairCost(primary.pairs, frequency) + + rawByteMultiAnchorPairCost(confirm.pairs, frequency) + + rawByteMultiAnchorPairCost(guard.pairs, frequency), + at: primary.at, + }, true +} + +func rawByteMultiAnchorAddTable(table *[64]byte, pairs rawByteMultiAnchorPairSet, second bool, bit byte) { + for i := 0; i < int(pairs.n); i++ { + value := byte(pairs.pairs[i]) + if second { + value = byte(pairs.pairs[i] >> 8) + } + table[value&0x3f] |= bit + } +} + +func (filter *rawByteMultiAnchorFilter) confirmationGroup(offset uint8) (int, bool) { + for i := 0; i < int(filter.confirmN); i++ { + if filter.confirmOffset[i] == offset { + return i, true + } + } + if int(filter.confirmN) == len(filter.confirmOffset) { + return 0, false + } + group := int(filter.confirmN) + filter.confirmOffset[group] = offset + filter.confirmN++ + if offset > filter.maxConfirmOffset { + filter.maxConfirmOffset = offset + } + return group, true +} + +// makeRawByteMultiAnchorFilter compiles the shared tagged interior-pair screen +// at plan construction. It is intentionally available only after the compact +// direct raw map is proven. Rejected shapes leave Matcher.Each on the existing +// decoded enumerator without lazy state, allocations, or history thresholds. +func (p *searchPlan) makeRawByteMultiAnchorFilter(patterns []string) { + p.rawByteMulti = rawByteMultiAnchorFilter{} + if len(patterns) < 2 || len(patterns) > rawByteMultiAnchorGroups { + return + } + frequency := rawByteMultiAnchorFrequency(patterns) + for patternID, pattern := range patterns { + var units [rawByteMultiAnchorStartOffsets * rawByteMultiAnchorStartOffsets]rawByteMultiAnchorUnit + unitN := 0 + for at := 0; at < len(pattern); { + r, size := utf8.DecodeRuneInString(pattern[at:]) + if r == utf8.RuneError && size == 1 { + return + } + if pairs, ok := rawByteMultiAnchorPairSetFor(r); ok { + if unitN == len(units) { + return + } + units[unitN] = rawByteMultiAnchorUnit{at: at, pairs: pairs} + unitN++ + } + at += size + } + var best rawByteMultiAnchorCandidate + found := false + for primary := 0; primary < unitN; primary++ { + for confirm := primary + 1; confirm < unitN; confirm++ { + for guard := confirm + 1; guard < unitN; guard++ { + candidate, ok := rawByteMultiAnchorCandidateFor(pattern, units[primary], units[confirm], units[guard], &frequency) + if !ok || !p.rawByteMulti.canAddConfirmationOffsets(candidate.anchor.confirmOffset[:candidate.anchor.confirmN]) { + continue + } + if !found || candidate.anchor.confirmN < best.anchor.confirmN || + candidate.anchor.confirmN == best.anchor.confirmN && (candidate.score < best.score || candidate.score == best.score && candidate.at > best.at) { + best, found = candidate, true + } + } + } + } + if !found { + p.rawByteMulti = rawByteMultiAnchorFilter{} + return + } + bit := byte(1 << uint(patternID)) + rawByteMultiAnchorAddTable(&p.rawByteMulti.first, best.anchor.primary, false, bit) + rawByteMultiAnchorAddTable(&p.rawByteMulti.second, best.anchor.primary, true, bit) + for i := 0; i < int(best.anchor.confirmN); i++ { + group, ok := p.rawByteMulti.confirmationGroup(best.anchor.confirmOffset[i]) + if !ok { + p.rawByteMulti = rawByteMultiAnchorFilter{} + return + } + rawByteMultiAnchorAddTable(&p.rawByteMulti.confirmFirst[group], best.anchor.confirm, false, bit) + rawByteMultiAnchorAddTable(&p.rawByteMulti.confirmSecond[group], best.anchor.confirm, true, bit) + if best.anchor.confirmOffset[i] > p.rawByteMulti.maxOffset { + p.rawByteMulti.maxOffset = best.anchor.confirmOffset[i] + } + } + p.rawByteMulti.anchors[patternID] = best.anchor + for i := 0; i < int(best.anchor.startN); i++ { + if best.anchor.starts[i] > p.rawByteMulti.maxOffset { + p.rawByteMulti.maxOffset = best.anchor.starts[i] + } + } + for i := 0; i < int(best.anchor.guardN); i++ { + if best.anchor.guardOffset[i] > p.rawByteMulti.maxOffset { + p.rawByteMulti.maxOffset = best.anchor.guardOffset[i] + } + } + } + // A table with one effective tag signature is not a selective multi-anchor + // filter. It cannot eliminate any shared-prefix alternative before the + // expensive raw-plan replays, so leave this plan on its existing fallback. + if !p.rawByteMulti.tagDiverse() { + p.rawByteMulti = rawByteMultiAnchorFilter{} + return + } + p.rawByteMulti.valid = 1 +} + +func (filter *rawByteMultiAnchorFilter) canAddConfirmationOffsets(offsets []uint8) bool { + n := int(filter.confirmN) + var pending [rawByteMultiAnchorConfirmGroups]uint8 + for _, offset := range offsets { + found := false + for i := 0; i < int(filter.confirmN); i++ { + found = found || filter.confirmOffset[i] == offset + } + for i := 0; i < n; i++ { + found = found || pending[i] == offset + } + if !found { + if n == len(pending) { + return false + } + pending[n] = offset + n++ + } + } + return true +} + +// tagsAt applies exact pair checks only for tags retained by the vector or +// scalar table screen. It retains literal tags that own the primary, +// fixed-displacement confirmation, and scalar guard simultaneously. +func (anchor rawByteMultiAnchor) maxOffset() int { + max := 0 + for i := 0; i < int(anchor.confirmN); i++ { + if offset := int(anchor.confirmOffset[i]); offset > max { + max = offset + } + } + for i := 0; i < int(anchor.guardN); i++ { + if offset := int(anchor.guardOffset[i]); offset > max { + max = offset + } + } + return max +} + +func (filter *rawByteMultiAnchorFilter) tagsAt(s string, at int, candidates byte) byte { + if !filter.usable() { + return 0 + } + var tags byte + for candidates != 0 { + i := bits.TrailingZeros8(candidates) + candidates &= candidates - 1 + anchor := filter.anchors[i] + if anchor.startN == 0 || at+anchor.maxOffset()+1 >= len(s) || !anchor.primary.matches(s, at) { + continue + } + confirmed := false + for j := 0; j < int(anchor.confirmN); j++ { + confirmed = confirmed || anchor.confirm.matches(s, at+int(anchor.confirmOffset[j])) + } + if !confirmed { + continue + } + guarded := false + for j := 0; j < int(anchor.guardN); j++ { + guarded = guarded || anchor.guard.matches(s, at+int(anchor.guardOffset[j])) + } + if guarded { + tags |= 1 << uint(i) + } + } + return tags +} + +func rawByteMultiAnchorSkipScalar(s string, at int, filter *rawByteMultiAnchorFilter) (int, byte) { + start := at + for at+1 < len(s) { + // The vector loop has already reduced these same low-six-bit tables. + // Keep its conservative predicate in the scalar tail, then let the + // caller run tagsAt's exact pair and guard checks only at a survivor. + tags := filter.first[s[at]&0x3f] + if tags != 0 { + tags &= filter.second[s[at+1]&0x3f] + var candidates byte + for group := 0; tags != 0 && group < int(filter.confirmN); group++ { + offset := int(filter.confirmOffset[group]) + if at+offset+1 >= len(s) { + continue + } + confirmed := filter.confirmFirst[group][s[at+offset]&0x3f] & + filter.confirmSecond[group][s[at+offset+1]&0x3f] + candidates |= tags & confirmed + } + if candidates != 0 { + return at - start, candidates + } + } + at++ + } + return at - start, 0 +} + +// rawByteMatchAt confirms only an anchored start. It retains the same raw +// two-byte map and decoded fallback as findFiltered, but does not let a later +// root found through a failure link impersonate a match at start. +func (p *searchPlan) rawByteMatchAt(haystack string, start int) (Match, int, bool) { + state, at := 0, start + for units := 1; units <= p.maxUnits && at < len(haystack); units++ { + next, size, raw := p.rawByteAdvance(haystack, at, state) + if !raw { + token, decodedSize := p.haystackToken(haystack, at) + next, size = p.advance(state, token), decodedSize + } + state = next + at += size + if output := p.nodes[state].output; output.pattern >= 0 && output.units == units { + return Match{Pattern: output.pattern, Start: start}, at - start, true + } + if state == 0 { + return Match{}, 0, false + } + } + return Match{}, 0, false +} + +// findRawByteFixedAnchored is the first-result specialization of the same +// tagged scan used by Matcher.Each. Stopping its callback leaves the shared +// scan only after it has waited through every compiled primary-start offset, so +// it preserves Find's leftmost and lowest-ID contract without a second engine. +func (p *searchPlan) findRawByteFixedAnchored(haystack string) (Match, bool) { + var result Match + found := false + p.eachRawByteFixedAnchored(haystack, func(match Match, _ int) bool { + result, found = match, true + return false + }) + return result, found +} + +// findRawByteOrigin begins the tagged scan at the only suffix that can contain +// a match. The exact-byte scan and the tagged/raw-plan replay retain authority +// over malformed input, fold spelling, leftmost order, and pattern-ID ties. +func (p *searchPlan) findRawByteOrigin(haystack string) (Match, bool) { + gate := p.rawByteOrigin + at := literalSkipExactASCII(haystack, 0, gate.byte) + if at == len(haystack) { + return Match{}, false + } + from := at - int(gate.maxPrefix) + if from < 0 { + from = 0 + } + match, ok := p.findRawByteFixedAnchored(haystack[from:]) + if ok { + match.Start += from + } + return match, ok +} + +// eachRawByteFixedAnchored enumerates with one shared tagged interior-pair +// scan. The table only nominates starts; exact pair checks and raw-plan replay +// keep Unicode folding, malformed bytes, leftmost order, and lowest-ID ties in +// the existing state machine. +func (p *searchPlan) eachRawByteFixedAnchored(haystack string, yield func(Match, int) bool) bool { + filter := &p.rawByteMulti + if !filter.usable() { + return true + } + + at, from := 0, 0 + best := Match{Pattern: -1, Start: -1} + bestEnd := 0 + emit := func() bool { + if !yield(best, bestEnd-best.Start) { + return false + } + at, from = bestEnd, bestEnd + best, bestEnd = Match{Pattern: -1, Start: -1}, 0 + return true + } + + for at+1 < len(haystack) { + if best.Pattern >= 0 && at > best.Start+int(filter.maxOffset) { + if !emit() { + return false + } + continue + } + skipped, candidates := rawByteMultiAnchorSkipBytes(haystack, at, filter) + at += skipped + if at+1 >= len(haystack) { + break + } + for tags := filter.tagsAt(haystack, at, candidates); tags != 0; tags &= tags - 1 { + patternID := bits.TrailingZeros8(tags) + anchor := filter.anchors[patternID] + for i := 0; i < int(anchor.startN); i++ { + start := at - int(anchor.starts[i]) + if start < from || best.Pattern >= 0 && start > best.Start { + continue + } + match, width, ok := p.rawByteMatchAt(haystack, start) + if !ok || best.Pattern >= 0 && match.Start > best.Start { + continue + } + if best.Pattern < 0 || match.Start < best.Start || + match.Start == best.Start && match.Pattern < best.Pattern { + best, bestEnd = match, match.Start+width + } + } + } + at++ + } + if best.Pattern >= 0 { + return yield(best, bestEnd-best.Start) + } + return true +} diff --git a/raw_byte_bench_fixture_test.go b/raw_byte_bench_fixture_test.go new file mode 100644 index 0000000..68b6b3d --- /dev/null +++ b/raw_byte_bench_fixture_test.go @@ -0,0 +1,93 @@ +package casei + +import "strings" + +// These benchmark fixture sizes are independent of raw-plan admission. They +// make the construction and candidate-density shapes available before the +// transition optimization so the same public benchmark can measure both arms. +const ( + rawByteBenchmarkCorpusBytes = 2 << 20 + rawBytePublicationCorpusBytes = 5 << 20 + rawByteFreshSampleBytes = 4 << 10 +) + +var rawByteCyrillicPatterns = []string{ + "Шерлок Холмс", + "Джон Уотсон", + "Ирен Адлер", + "инспектор Лестрейд", + "профессор Мориарти", +} + +// rawByteFalseCandidates emits ordinary Cyrillic root units followed by an +// ASCII mismatch. Each planted start reaches exactly two shared-plan unit +// transitions: the root and the reset byte. +func rawByteFalseCandidates(period, groups int) string { + if period < len("Дx") { + panic("raw byte candidate period is too short") + } + bytes := []byte(strings.Repeat("x", period*groups)) + for at := 0; at+len("Дx") <= len(bytes); at += period { + copy(bytes[at:], "Дx") + } + return string(bytes) +} + +// rawByteFalseCandidatesAtLeast rounds groups up so fixtures cross a requested +// byte boundary even when the candidate period does not divide it. +func rawByteFalseCandidatesAtLeast(period, bytes int) string { + return rawByteFalseCandidates(period, (bytes+period-1)/period) +} + +// rawByteLateMatchCandidatesAtLeast keeps the same repeated false-root shape +// through the final sample window, then replaces one late slot with the first +// literal. The returned offset is the ordinary byte offset of that occurrence. +func rawByteLateMatchCandidatesAtLeast(period, bytes int) (string, int) { + pattern := rawByteCyrillicPatterns[0] + if period < len(pattern) { + panic("raw byte late-match period is too short") + } + out := []byte(rawByteFalseCandidatesAtLeast(period, bytes)) + start := len(out) - period + copy(out[start:], pattern) + return string(out), start +} + +// rawByteEarlyMatchCandidatesAtLeast plants one complete literal at a fixed +// early offset while retaining a long dense suffix. It guards the public Find +// call that can stop before later admission sample windows. +func rawByteEarlyMatchCandidatesAtLeast(period, bytes, start int) (string, int) { + pattern := rawByteCyrillicPatterns[0] + if period < len(pattern) || start < 0 || start%period != 0 { + panic("invalid raw byte early-match placement") + } + out := []byte(rawByteFalseCandidatesAtLeast(period, bytes)) + if start+len(pattern) > len(out) { + panic("raw byte early match is outside its corpus") + } + copy(out[start:], pattern) + return string(out), start +} + +// rawByteNearMissCandidates plants a whole literal prefix with a final Cyrillic +// mismatch. It exercises candidate confirmation without returning a match. +func rawByteNearMissCandidates(period, groups int) string { + const nearMiss = "Шерлок Холми" + if period < len(nearMiss) { + panic("raw byte near-miss period is too short") + } + bytes := []byte(strings.Repeat("x", period*groups)) + for at := 0; at+len(nearMiss) <= len(bytes); at += period { + copy(bytes[at:], nearMiss) + } + return string(bytes) +} + +func rawByteNearMissCandidatesAtLeast(period, bytes int) string { + return rawByteNearMissCandidates(period, (bytes+period-1)/period) +} + +func rawByteLongPrefixPatterns() []string { + prefix := strings.Repeat("Д", 100) + return []string{prefix + "a", prefix + "b"} +} diff --git a/raw_byte_multi_anchor_amd64_test.go b/raw_byte_multi_anchor_amd64_test.go new file mode 100644 index 0000000..713aea0 --- /dev/null +++ b/raw_byte_multi_anchor_amd64_test.go @@ -0,0 +1,169 @@ +//go:build amd64 + +package casei + +import ( + "math/rand/v2" + "strings" + "testing" + "unsafe" + + "golang.org/x/sys/cpu" +) + +// rawByteMultiAnchorVectorResult models only the conservative table predicate +// implemented by rawByteMultiAnchorSkip64. Exact primary/guard checks belong +// to tagsAt and intentionally occur after this candidate screen. +func rawByteMultiAnchorVectorResult(s string, at int, filter *rawByteMultiAnchorFilter) (int, byte) { + start := at + for len(s)-at >= 65+int(filter.maxConfirmOffset) { + for lane := 0; lane < 64; lane++ { + primary := filter.first[s[at+lane]&0x3f] & filter.second[s[at+lane+1]&0x3f] + var tags byte + for group := 0; group < rawByteMultiAnchorConfirmGroups; group++ { + offset := int(filter.confirmOffset[group]) + confirm := filter.confirmFirst[group][s[at+lane+offset]&0x3f] & + filter.confirmSecond[group][s[at+lane+offset+1]&0x3f] + tags |= primary & confirm + } + if tags != 0 { + return at - start + lane, tags + } + } + at += 64 + } + return at - start, 0 +} + +// rawByteMultiAnchorDenseNoConfirmPrefix constructs a fixed counterexample to +// an unbounded dense schedule: two of the first four primary masks are set, +// but no vector-confirmed lane occurs before the sparse suffix. +func rawByteMultiAnchorDenseNoConfirmPrefix(t *testing.T, filter *rawByteMultiAnchorFilter) string { + t.Helper() + buf := make([]byte, 512) + seed := uint32(1) + for attempt := 0; attempt < 10000; attempt++ { + for i := range buf { + seed = seed*1664525 + 1013904223 + buf[i] = byte(seed >> 24) + } + occupied := 0 + for block := 0; block < 4; block++ { + for lane := 0; lane < 64; lane++ { + at := block*64 + lane + if filter.first[buf[at]&0x3f]&filter.second[buf[at+1]&0x3f] != 0 { + occupied++ + break + } + } + } + candidate := string(buf[:256]) + skipped, _ := rawByteMultiAnchorVectorResult(candidate, 0, filter) + if occupied >= 2 && skipped >= 192 { + return candidate + } + } + t.Fatal("could not construct a dense/no-confirm prefix") + return "" +} + +func TestRawByteMultiAnchorDenseEpochMatchesTableModel(t *testing.T) { + if !cpu.X86.HasAVX512F || !cpu.X86.HasAVX512BW || !cpu.X86.HasAVX512VBMI { + t.Skip("AVX-512 VBMI multi-anchor path is disabled") + } + plan := newSearchPlan(rawByteCyrillicPatterns) + filter := &plan.rawByteMulti + if !filter.usable() { + t.Fatal("eligible plan did not compile a raw multi-anchor filter") + } + prefix := rawByteMultiAnchorDenseNoConfirmPrefix(t, filter) + for _, tc := range []struct { + name string + haystack string + }{ + {"dense_prefix_sparse_suffix", prefix + strings.Repeat("x", 5<<20)}, + {"uniform_dense_no_confirm", strings.Repeat(prefix, 1<<14)}, + } { + t.Run(tc.name, func(t *testing.T) { + want, wantTags := rawByteMultiAnchorVectorResult(tc.haystack, 0, filter) + if want < len(tc.haystack)-128 { + t.Fatalf("fixture unexpectedly has a vector tag at %d", want) + } + got, gotTags := rawByteMultiAnchorSkip64(unsafe.StringData(tc.haystack), len(tc.haystack), filter) + if got != want || gotTags != wantTags { + t.Fatalf("rawByteMultiAnchorSkip64 = %d,%02x, want %d,%02x", got, gotTags, want, wantTags) + } + }) + } +} + +func TestRawByteMultiAnchorScalarFallbackPreservesMatches(t *testing.T) { + if !cpu.X86.HasAVX512F || !cpu.X86.HasAVX512BW || !cpu.X86.HasAVX512VBMI { + t.Skip("AVX-512 VBMI multi-anchor path is disabled") + } + prior := cpu.X86.HasAVX512VBMI + cpu.X86.HasAVX512VBMI = false + defer func() { cpu.X86.HasAVX512VBMI = prior }() + + patterns := append(append([]string(nil), rawByteCyrillicPatterns...), strings.ToLower(rawByteCyrillicPatterns[0])) + matcher := NewMatcher(patterns) + if !matcher.plan.rawByteMulti.usable() { + t.Fatal("eligible scalar-fallback plan did not compile a multi-anchor filter") + } + inputs := []string{ + strings.Repeat("x", 129) + rawByteCyrillicPatterns[0], + strings.Repeat("x", 71) + "\xff" + rawByteCyrillicPatterns[3], + "ᲁжон уотсон " + rawByteCyrillicPatterns[2], + strings.Repeat("x", 63) + rawByteCyrillicPatterns[1] + strings.Repeat("x", 17) + rawByteCyrillicPatterns[0], + } + rng := rand.New(rand.NewPCG(20260908, 10)) + units := []string{"x", "Д", "д", "ᲁ", "Ж", "ж", "Ш", "ш", "K", "ſ", "\xff", "\x80", "€"} + for iteration := 0; iteration < 128; iteration++ { + var haystack strings.Builder + for range 64 { + haystack.WriteString(units[rng.IntN(len(units))]) + } + if iteration%3 == 0 { + haystack.WriteString(patterns[rng.IntN(len(patterns))]) + } + inputs = append(inputs, haystack.String()) + } + for inputIndex, haystack := range inputs { + got, gotOK := matcher.Find(haystack) + want, wantOK := refFind(haystack, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("input %d Find(%x) = %+v,%t; want %+v,%t", inputIndex, haystack, got, gotOK, want, wantOK) + } + rawByteCheckEach(t, matcher, haystack) + } +} + +func TestRawByteMultiAnchorVBMISkip64MatchesTableModel(t *testing.T) { + if !cpu.X86.HasAVX512F || !cpu.X86.HasAVX512BW || !cpu.X86.HasAVX512VBMI { + t.Skip("AVX-512 VBMI multi-anchor path is disabled") + } + plan := newSearchPlan(rawByteCyrillicPatterns) + filter := &plan.rawByteMulti + if !filter.usable() { + t.Fatal("eligible plan did not compile a raw multi-anchor filter") + } + + rng := rand.New(rand.NewPCG(20260827, 4)) + // Cross the 512-byte sparse aggregate boundary as well as every tail + // alignment below it. The assembly must replay its four-block dispatcher + // without changing the earliest conservative table survivor. + for length := 0; length < 768; length++ { + input := make([]byte, length) + for i := range input { + input[i] = byte(rng.Uint32()) + } + haystack := string(input) + for at := range haystack { + want, wantTags := rawByteMultiAnchorVectorResult(haystack, at, filter) + got, gotTags := rawByteMultiAnchorSkip64((*byte)(unsafe.Add(unsafe.Pointer(unsafe.StringData(haystack)), at)), len(haystack)-at, filter) + if got != want || gotTags != wantTags { + t.Fatalf("length %d at %d: rawByteMultiAnchorSkip64 = %d,%02x, want %d,%02x", length, at, got, gotTags, want, wantTags) + } + } + } +} diff --git a/raw_byte_test.go b/raw_byte_test.go new file mode 100644 index 0000000..19025fa --- /dev/null +++ b/raw_byte_test.go @@ -0,0 +1,513 @@ +package casei + +import ( + "math/rand/v2" + "strings" + "testing" + "unicode/utf8" +) + +func TestRawByteTokenPlanDirectTransitions(t *testing.T) { + plan := newSearchPlan(rawByteCyrillicPatterns) + if !plan.hasRawByteTokenPlan() { + t.Fatal("eligible Cyrillic plan did not retain a compact raw-byte map") + } + for state := range plan.nodes { + for value := range utf8.RuneSelf { + haystack := string([]byte{byte(value)}) + got, size, ok := plan.rawByteAdvance(haystack, 0, state) + wantToken, wantSize := plan.haystackToken(haystack, 0) + want := plan.advance(state, wantToken) + if !ok || size != wantSize || got != want { + t.Fatalf("state %d ASCII %02x: raw=(%d,%d,%t), decoded=(%d,%d)", + state, value, got, size, ok, want, wantSize) + } + } + for lead := 0xc2; lead <= 0xdf; lead++ { + for trail := 0x80; trail <= 0xbf; trail++ { + haystack := string([]byte{byte(lead), byte(trail)}) + got, size, ok := plan.rawByteAdvance(haystack, 0, state) + wantToken, wantSize := plan.haystackToken(haystack, 0) + want := plan.advance(state, wantToken) + if !ok || size != wantSize || got != want { + t.Fatalf("state %d UTF-8 %02x%02x: raw=(%d,%d,%t), decoded=(%d,%d)", + state, lead, trail, got, size, ok, want, wantSize) + } + } + } + } + + for _, haystack := range []string{"\x80", "\xc2x", "€", "K"} { + if _, _, ok := plan.rawByteAdvance(haystack, 0, 0); ok { + t.Fatalf("unsupported input %x entered the raw-byte map", haystack) + } + } +} + +// rawByteFilteredDirectTransitions mirrors the non-skipped portion of +// findFiltered for a no-match stream. It verifies that the public filtered +// route reaches the compact raw map rather than merely compiling it. +func rawByteFilteredDirectTransitions(t *testing.T, plan *searchPlan, haystack string) int { + t.Helper() + if !plan.hasRawByteTokenPlan() { + t.Fatal("plan has no compact raw-byte map") + } + + state, transitions := 0, 0 + for at := 0; at < len(haystack); { + if state == 0 { + skipped := len(haystack) - at + if plan.pairSecond { + skipped = pairSecondSkipBytes(haystack, at, &plan.filter) + } else if plan.filter.usable() { + skipped = filterSkipBytes(haystack, at, &plan.filter) + } + if plan.triples.usable() { + if tripleSkipped := tripleSkipBytes(haystack, at, &plan.triples); tripleSkipped < skipped { + skipped = tripleSkipped + } + } + at += skipped + if at == len(haystack) { + break + } + } + + rawState, rawSize, rawOK := plan.rawByteAdvance(haystack, at, state) + token, decodedSize := plan.haystackToken(haystack, at) + decodedState := plan.advance(state, token) + if !rawOK || rawSize != decodedSize || rawState != decodedState { + t.Fatalf("transition at byte %d: raw=(state=%d,size=%d,ok=%t), decoded=(state=%d,size=%d)", + at, rawState, rawSize, rawOK, decodedState, decodedSize) + } + state = rawState + transitions++ + at += rawSize + } + return transitions +} + +func rawByteSharedPrefixPatterns(n int) []string { + patterns := make([]string, n) + for i := range patterns { + patterns[i] = "щупальце" + string(rune('0'+i)) + } + return patterns +} + +func TestRawByteMultiAnchorRequiresTagDiversity(t *testing.T) { + for _, n := range []int{2, 4, 8} { + patterns := rawByteSharedPrefixPatterns(n) + plan := newSearchPlan(patterns) + if !plan.hasRawByteTokenPlan() { + t.Fatalf("N=%d shared-prefix plan lost the compact raw-byte map", n) + } + if plan.rawByteMulti.usable() { + t.Fatalf("N=%d indistinguishable shared-prefix anchors entered rawByteMulti", n) + } + matcher := NewMatcher(patterns) + for _, haystack := range []string{ + strings.Repeat("щ", 63) + "упальцеx", + "ᲇупальце7", // width-changing fold spelling before the shared suffix. + strings.Repeat("x", 71) + "\xff" + patterns[n-1], + } { + got, gotOK := matcher.Find(haystack) + want, wantOK := refFind(haystack, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("N=%d Find(%x) = %+v,%t; want %+v,%t", n, haystack, got, gotOK, want, wantOK) + } + } + } + + diverse := []string{ + "абвгде0", "ёжзийк1", "лмнопр2", "стуфхц3", + "чшщьыъ4", "ыьэюяа5", "бвгдеж6", "зийклм7", + } + for _, patterns := range [][]string{rawByteCyrillicPatterns, diverse} { + plan := newSearchPlan(patterns) + if !plan.rawByteMulti.usable() || !plan.rawByteMulti.tagDiverse() { + t.Fatalf("diverse anchors were not admitted: patterns=%q usable=%t diverse=%t", patterns, plan.rawByteMulti.usable(), plan.rawByteMulti.tagDiverse()) + } + } +} + +func TestRawByteFilteredDensityUsesDirectTransitions(t *testing.T) { + for _, tc := range []struct { + name string + patterns []string + period int + groups int + }{ + {"two_one_in_32", rawByteCyrillicPatterns[:2], 32, 4096 / 32}, + {"five_one_in_256", rawByteCyrillicPatterns, 256, rawBytePublicationCorpusBytes / 256}, + {"five_one_in_4", rawByteCyrillicPatterns, 4, rawByteBenchmarkCorpusBytes / 16 / 4}, + } { + t.Run(tc.name, func(t *testing.T) { + haystack := rawByteFalseCandidates(tc.period, tc.groups) + plan := newSearchPlan(tc.patterns) + if plan.unicodePairN != 0 || plan.unicodeAnchor.n != 0 || !plan.filter.usable() { + t.Fatalf("fixture does not select generic filtered search: pairs=%d anchor=%d filter=%t", + plan.unicodePairN, plan.unicodeAnchor.n, plan.filter.usable()) + } + if got := rawByteFilteredDirectTransitions(t, plan, haystack); got != 2*tc.groups { + t.Fatalf("direct non-skipped transitions = %d, want %d", got, 2*tc.groups) + } + + matcher := NewMatcher(tc.patterns) + if got, ok := matcher.Find(haystack); ok || got != (Match{}) { + t.Fatalf("Find = %+v,%t, want no match", got, ok) + } + if !matcher.plan.hasRawByteTokenPlan() { + t.Fatal("public Matcher.Find did not retain the compact raw-byte map") + } + }) + } +} + +func TestRawByteTokenPlanPreservesFallbackOffsetsAndTies(t *testing.T) { + patterns := append(append([]string(nil), rawByteCyrillicPatterns...), "ДЖОН УОТСОН") + matcher := NewMatcher(patterns) + if !matcher.plan.hasRawByteTokenPlan() { + t.Fatal("eligible multi-pattern plan did not retain a raw-byte map") + } + + for _, haystack := range []string{ + "ᲁЖОН УОТСОН", // U+1C81 is a three-byte simple-fold spelling of Д. + strings.Repeat("x", 31) + "\xff" + strings.Repeat("x", 17) + "ДЖОН УОТСОН", + strings.Repeat("x", 29) + "K" + strings.Repeat("x", 11) + "ШЕРЛОК ХОЛМС", + strings.Repeat("x", 23) + "ДЖОН УОТСОН", + } { + got, gotOK := matcher.Find(haystack) + want, wantOK := refFind(haystack, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("Find(%x) = %+v,%t; want %+v,%t", haystack, got, gotOK, want, wantOK) + } + } + + rng := rand.New(rand.NewPCG(20260824, 1)) + units := []string{"x", " ", "Д", "д", "ᲁ", "Ж", "ж", "Ш", "ш", "K", "ſ", "\xff", "\x80", "€"} + for iteration := 0; iteration < 1000; iteration++ { + var haystack strings.Builder + for range 96 { + haystack.WriteString(units[rng.IntN(len(units))]) + } + if iteration%3 == 0 { + haystack.WriteString(patterns[rng.IntN(len(rawByteCyrillicPatterns))]) + } + input := haystack.String() + got, gotOK := matcher.Find(input) + want, wantOK := refFind(input, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("iteration %d Find(%x) = %+v,%t; want %+v,%t", iteration, input, got, gotOK, want, wantOK) + } + } +} + +func TestRawByteOriginGatePreservesFind(t *testing.T) { + plan := newSearchPlan(rawByteCyrillicPatterns) + if !plan.rawByteMulti.usable() || !plan.rawByteOrigin.usable() { + t.Fatal("eligible plan did not compile the tagged filter and origin gate") + } + matcher := NewMatcher(rawByteCyrillicPatterns) + check := func(name, haystack string) { + t.Helper() + want, wantOK := refFind(haystack, rawByteCyrillicPatterns) + for _, route := range []struct { + name string + find func(string) (Match, bool) + }{ + {"direct", plan.findRawByteOrigin}, + {"public", matcher.Find}, + } { + got, gotOK := route.find(haystack) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("%s/%s: Find(%x) = %+v,%t; want %+v,%t", name, route.name, haystack, got, gotOK, want, wantOK) + } + } + } + + check("absent", strings.Repeat("x", 5<<10)) + check("unrelated-earlier-gate", strings.Repeat("x", 97)+" "+strings.Repeat("x", 5<<10)+rawByteCyrillicPatterns[3]) + check("opaque-before-match", strings.Repeat("x", 5<<10)+"\xff"+rawByteCyrillicPatterns[2]) + for alignment := 0; alignment < 64; alignment++ { + // U+1C81 is a three-byte rendering of the pattern's initial Д. Its + // varying source width exercises the gate's maximum-prefix lookback. + check("width-changing-prefix", strings.Repeat("x", 4096+alignment)+"ᲁЖОН УОТСОН") + } + + if gate := rawByteOriginGateFor([]string{"абв", "где"}); gate.usable() { + t.Fatalf("patterns with no common fold-invariant ASCII byte compiled gate %+v", gate) + } + if gate := rawByteOriginGateFor([]string{"абв ", "где \xff"}); gate.usable() { + t.Fatalf("malformed pattern compiled gate %+v", gate) + } +} + +type rawByteEachResult struct { + match Match + width int +} + +// rawByteReferenceEach is deliberately independent from Matcher.Find and the +// compiled transition plan. It reduces the canonical fold reference used by +// the package tests to the non-overlapping enumeration contract. +func rawByteReferenceEach(haystack string, patterns []string) []rawByteEachResult { + var out []rawByteEachResult + for at := 0; at <= len(haystack); { + match, ok := refFind(haystack[at:], patterns) + if !ok { + return out + } + match.Start += at + canon, _ := canonFold(patterns[match.Pattern]) + _, offsets := canonFold(haystack[match.Start:]) + width := offsets[len(canon)] + out = append(out, rawByteEachResult{match, width}) + at = match.Start + width + } + return out +} + +func rawByteCheckEach(t *testing.T, matcher *Matcher, haystack string) { + t.Helper() + want := rawByteReferenceEach(haystack, matcher.patterns) + var got []rawByteEachResult + if complete := matcher.Each(haystack, func(match Match, width int) bool { + got = append(got, rawByteEachResult{match, width}) + return true + }); !complete { + t.Fatal("Each stopped before completing enumeration") + } + if len(got) != len(want) { + t.Fatalf("Each(%x) returned %d matches, want %d: got=%+v want=%+v", haystack, len(got), len(want), got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("Each(%x) match %d = %+v, want %+v", haystack, i, got[i], want[i]) + } + } +} + +// TestRawByteMultiAnchorFindOrderingAndTail exercises the first-result view of +// the shared tagged scan. It keeps a duplicate fold-equivalent literal so the +// exact replay, rather than tag iteration order, must select the lowest ID. +func TestRawByteMultiAnchorFindOrderingAndTail(t *testing.T) { + patterns := append(append([]string(nil), rawByteCyrillicPatterns...), strings.ToLower(rawByteCyrillicPatterns[0])) + matcher := NewMatcher(patterns) + if !matcher.plan.rawByteMulti.usable() { + t.Fatal("eligible Find plan did not compile a raw multi-anchor filter") + } + + check := func(name, haystack string) { + t.Helper() + got, gotOK := matcher.Find(haystack) + want, wantOK := refFind(haystack, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("%s: Find(%x) = %+v,%t; want %+v,%t", name, haystack, got, gotOK, want, wantOK) + } + } + + // Shift the final literal through every vector-tail alignment. The prefix + // is long enough to take the VBMI scan before its scalar tail reaches the + // candidate; the duplicate pattern checks the lowest-ID tie at that tail. + for alignment := 0; alignment < 64; alignment++ { + check("tail", strings.Repeat("x", 128+alignment)+rawByteCyrillicPatterns[0]) + } + + check("earlier-start-wins", rawByteCyrillicPatterns[3]+" x "+rawByteCyrillicPatterns[0]) + check("opaque-before-match", strings.Repeat("x", 91)+"\xff"+rawByteCyrillicPatterns[2]) + // U+1C81 is the three-byte simple-fold spelling of the initial Д. The + // compiled start offsets may nominate extras, but exact raw-plan replay must + // still return the same ordinary byte offset as the reference. + check("width-changing-before-anchor", strings.Repeat("x", 77)+"ᲁжон уотсон") +} + +func TestRawByteMultiAnchorEnumeration(t *testing.T) { + matcher := NewMatcher(rawByteCyrillicPatterns) + if !matcher.plan.hasRawByteTokenPlan() || !matcher.plan.rawByteMulti.usable() { + t.Fatalf("eligible plan did not compile raw multi-anchor state: raw=%t multi=%t", matcher.plan.hasRawByteTokenPlan(), matcher.plan.rawByteMulti.usable()) + } + + // Sweep every vector tail alignment. The second occurrence forces a resume + // after a nonzero width, while the last one makes the selected anchor cross + // from a vector block into the scalar tail. + for alignment := 0; alignment < 64; alignment++ { + haystack := rawByteCyrillicPatterns[0] + strings.Repeat("x", alignment) + rawByteCyrillicPatterns[2] + rawByteCheckEach(t, matcher, haystack) + } + + for _, haystack := range []string{ + "ᲁжон уотсон " + rawByteCyrillicPatterns[2], // width-changing Д form before an anchor. + strings.Repeat("x", 71) + "\xff" + rawByteCyrillicPatterns[3], + strings.Repeat("ж", 83) + rawByteCyrillicPatterns[4], + strings.Repeat("x", 19) + rawByteCyrillicPatterns[1] + rawByteCyrillicPatterns[0], + } { + rawByteCheckEach(t, matcher, haystack) + } + + rng := rand.New(rand.NewPCG(20260826, 3)) + units := []string{"x", " ", "Д", "д", "ᲁ", "Ж", "ж", "Ш", "ш", "О", "ᲂ", "о", "Н", "н", "И", "и", "€", "\xff", "\x80"} + for iteration := 0; iteration < 512; iteration++ { + var haystack strings.Builder + for range 96 { + haystack.WriteString(units[rng.IntN(len(units))]) + } + for i := 0; i < iteration%5; i++ { + haystack.WriteString(rawByteCyrillicPatterns[rng.IntN(len(rawByteCyrillicPatterns))]) + haystack.WriteString(" xx ") + } + rawByteCheckEach(t, matcher, haystack.String()) + } +} + +func TestRawByteMultiAnchorSkipNeverPassesAConfirmedTag(t *testing.T) { + plan := newSearchPlan(rawByteCyrillicPatterns) + filter := &plan.rawByteMulti + if !filter.usable() { + t.Fatal("eligible plan did not compile a raw multi-anchor filter") + } + for alignment := 0; alignment < 64; alignment++ { + haystack := strings.Repeat("x", alignment+128) + rawByteCyrillicPatterns[alignment%len(rawByteCyrillicPatterns)] + strings.Repeat("x", 96) + for at := range haystack { + skipped, _ := rawByteMultiAnchorSkipBytes(haystack, at, filter) + if skipped < 0 || at+skipped > len(haystack) { + t.Fatalf("alignment %d at %d: invalid skip %d", alignment, at, skipped) + } + for candidate := at; candidate < at+skipped; candidate++ { + if tags := filter.tagsAt(haystack, candidate, 0xff); tags != 0 { + t.Fatalf("alignment %d at %d: skip %d passed confirmed tag %08b at %d", alignment, at, skipped, tags, candidate) + } + } + } + } +} + +func TestRawByteMultiAnchorScalarScreenUnionsConfirmationGroups(t *testing.T) { + pair := func(first, second byte) rawByteMultiAnchorPairSet { + return rawByteMultiAnchorPairSet{ + pairs: [rawByteMultiAnchorForms]uint16{uint16(first) | uint16(second)<<8}, + n: 1, + } + } + const ( + aliasTag = byte(1 << iota) + matchTag + ) + aliasPrimary := pair(0x01, 0x02) // Low six bits alias "AB". + matchPrimary := pair('A', 'B') + aliasConfirm := pair('C', 'D') + matchConfirm := pair('E', 'F') + guard := pair('G', 'H') + filter := rawByteMultiAnchorFilter{ + confirmOffset: [rawByteMultiAnchorConfirmGroups]uint8{2, 4}, + confirmN: 2, + valid: 1, + } + rawByteMultiAnchorAddTable(&filter.first, aliasPrimary, false, aliasTag) + rawByteMultiAnchorAddTable(&filter.second, aliasPrimary, true, aliasTag) + rawByteMultiAnchorAddTable(&filter.first, matchPrimary, false, matchTag) + rawByteMultiAnchorAddTable(&filter.second, matchPrimary, true, matchTag) + rawByteMultiAnchorAddTable(&filter.confirmFirst[0], aliasConfirm, false, aliasTag) + rawByteMultiAnchorAddTable(&filter.confirmSecond[0], aliasConfirm, true, aliasTag) + rawByteMultiAnchorAddTable(&filter.confirmFirst[1], matchConfirm, false, matchTag) + rawByteMultiAnchorAddTable(&filter.confirmSecond[1], matchConfirm, true, matchTag) + filter.anchors[0] = rawByteMultiAnchor{ + primary: aliasPrimary, + confirm: aliasConfirm, + guard: guard, + starts: [rawByteMultiAnchorStartOffsets]uint8{0}, + confirmOffset: [rawByteMultiAnchorConfirmGroups]uint8{2}, + guardOffset: [rawByteMultiAnchorStartOffsets]uint8{6}, + startN: 1, + confirmN: 1, + guardN: 1, + } + filter.anchors[1] = rawByteMultiAnchor{ + primary: matchPrimary, + confirm: matchConfirm, + guard: guard, + starts: [rawByteMultiAnchorStartOffsets]uint8{0}, + confirmOffset: [rawByteMultiAnchorConfirmGroups]uint8{4}, + guardOffset: [rawByteMultiAnchorStartOffsets]uint8{6}, + startN: 1, + confirmN: 1, + guardN: 1, + } + + haystack := "ABCDEFGH" + skipped, candidates := rawByteMultiAnchorSkipScalar(haystack, 0, &filter) + if skipped != 0 || candidates != aliasTag|matchTag { + t.Fatalf("scalar screen = (%d, %08b), want (0, %08b)", skipped, candidates, aliasTag|matchTag) + } + if tags := filter.tagsAt(haystack, 0, candidates); tags != matchTag { + t.Fatalf("exact tags = %08b, want %08b", tags, matchTag) + } +} + +// TestRawByteMultiAnchorScalarScreenNeverPassesConfirmedTag proves the table +// screen used after a vector tail (and on portable hosts) can stop early on an +// alias but never skips an exact tagged anchor. The later tagsAt replay remains +// the match authority. +func TestRawByteMultiAnchorScalarScreenNeverPassesConfirmedTag(t *testing.T) { + plan := newSearchPlan(rawByteCyrillicPatterns) + filter := &plan.rawByteMulti + if !filter.usable() { + t.Fatal("eligible plan did not compile a raw multi-anchor filter") + } + inputs := []string{ + strings.Repeat("x", 257) + rawByteCyrillicPatterns[0], + strings.Repeat("x", 63) + "\xff\x80" + rawByteCyrillicPatterns[1], + strings.Repeat("x", 17) + "ᲁжон уотсон", + } + rng := rand.New(rand.NewPCG(20260907, 8)) + for i := 0; i < 256; i++ { + buf := make([]byte, i) + for j := range buf { + buf[j] = byte(rng.Uint32()) + } + inputs = append(inputs, string(buf)) + } + for inputIndex, haystack := range inputs { + for at := range haystack { + skipped, _ := rawByteMultiAnchorSkipScalar(haystack, at, filter) + if skipped < 0 || at+skipped > len(haystack) { + t.Fatalf("input %d at %d: invalid scalar skip %d", inputIndex, at, skipped) + } + for candidate := at; candidate < at+skipped; candidate++ { + if tags := filter.tagsAt(haystack, candidate, 0xff); tags != 0 { + t.Fatalf("input %d at %d: scalar skip %d passed confirmed tag %08b at %d", inputIndex, at, skipped, tags, candidate) + } + } + } + } +} + +func TestRawByteTokenPlanFallsBackForUnsupportedPlans(t *testing.T) { + for _, patterns := range [][]string{ + {"Шерлок"}, + {"Шерлок", "Δelta", "éclair"}, + {"\xffШерлок", "Джон"}, + } { + matcher := NewMatcher(patterns) + if matcher.plan.hasRawByteTokenPlan() { + t.Fatalf("unsupported plan %q retained raw-byte tokens", patterns) + } + input := "… δELTA … ÉCLAIR … ШЕРЛОК \xffДЖОН" + got, gotOK := matcher.Find(input) + want, wantOK := refFind(input, patterns) + if gotOK != wantOK || gotOK && got != want { + t.Fatalf("Find(%q, %x) = %+v,%t; want %+v,%t", patterns, input, got, gotOK, want, wantOK) + } + } +} + +func TestRawByteTokenPlanFindAllocatesNothingAfterConstruction(t *testing.T) { + matcher := NewMatcher(rawByteCyrillicPatterns) + haystack := rawByteFalseCandidatesAtLeast(64, 64<<10) + if got, ok := matcher.Find(haystack); ok || got != (Match{}) { + t.Fatalf("setup Find = %+v,%t", got, ok) + } + if allocs := testing.AllocsPerRun(100, func() { _, _ = matcher.Find(haystack) }); allocs != 0 { + t.Fatalf("reused raw-byte Find allocations = %g, want 0", allocs) + } +} diff --git a/root_amd64.go b/root_amd64.go index 54ca8aa..4986394 100644 --- a/root_amd64.go +++ b/root_amd64.go @@ -24,6 +24,10 @@ func asciiPairVBMIEnabled() bool { return cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && cpu.X86.HasAVX512VBMI } +func unicodePairConfirmVectorEnabled() bool { + return asciiPairVBMIEnabled() +} + // asciiFixedPrefix8 compares the compiled low eight pattern bytes after // applying case bits only at ASCII-letter positions. Its callers establish an // in-bounds eight-byte window before this unaligned amd64 load. @@ -50,6 +54,7 @@ func rootSkip32(ptr *byte, n int, target, fold uint64) int func rootSkip64(ptr *byte, n int, target, fold uint64) int func literalSkip32(ptr *byte, n int, target, fold uint64) int func literalSkip64(ptr *byte, n int, target, fold uint64) int +func literalSkipExact64(ptr *byte, n int, target uint64) int func runMask32(ptr *byte, target, fold uint64) uint32 func runMask64(ptr *byte, target, fold uint64) uint64 func probeSkip32(ptr *byte, n int, probe *asciiProbe) int @@ -65,6 +70,7 @@ func pairShuftiSkip64(ptr *byte, n int, filter *pairShuftiFilter) int func pairShuftiWithOnesSkip64(ptr *byte, n int, filter *pairShuftiFilter) int func pairPairSkip64(ptr *byte, n int, filter *pairPairFilter) int func pairPairVBMISkip64(ptr *byte, n int, filter *pairPairVBMIFilter) int +func pairPairConfirmVBMI64(ptr *byte, n int, filter *pairPairVBMIFilter, confirm *byte) (ret, width int) func pairPairWordSkip64(ptr *byte, n int, filter *pairPairFilter) int func pairSecondSkip32(ptr *byte, n int, filter *rootFilter) int func pairSecondSkip64(ptr *byte, n int, filter *rootFilter) int @@ -75,6 +81,7 @@ func filterSkip64(ptr *byte, n int, filter *rootFilter) int func tripleSkip32(ptr *byte, n int, filter *tripleFilter) int func tripleSkip64(ptr *byte, n int, filter *tripleFilter) int func tripleShuftiSkip64(ptr *byte, n int, filter *tripleShuftiFilter) int +func rawByteMultiAnchorSkip64(ptr *byte, n int, filter *rawByteMultiAnchorFilter) (ret int, tags byte) func asciiPairAnchorSkip64(ptr *byte, n int, filter *asciiPairAnchorFilter) int func asciiPairAnchorVBMISkip64(ptr *byte, n int, filter *asciiPairVBMIAnchorFilter) int func tripleSharedPrefixSkip64(ptr *byte, n int, filter *tripleFilter) int @@ -156,6 +163,28 @@ func literalSkipASCII(s string, at int, kind uint8, needle byte) int { return at - start } +// literalSkipExactASCII is the fixed-byte specialization used by a compiled +// universal literal. It scans through high and malformed bytes just like +// literalSkipASCII, but avoids the generic fold-zero vector operation. +func literalSkipExactASCII(s string, at int, needle byte) int { + start := at + remaining := len(s) - at + target := uint64(needle) * byteOnes + if cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && remaining >= 64 { + full := remaining &^ 63 + ptr := (*byte)(unsafe.Add(unsafe.Pointer(unsafe.StringData(s)), at)) + skipped := literalSkipExact64(ptr, remaining, target) + at += skipped + if skipped < full { + return at - start + } + } + for at < len(s) && s[at] != needle { + at++ + } + return at - start +} + func probeSkipBytes(s string, at, candidates int, probe *asciiProbe) int { start := at if cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && candidates >= 64 { @@ -433,6 +462,14 @@ func pairShuftiSkipBytes(s string, at int, filter *rootFilter) int { return at - start + pairShuftiSkipScalar(s, at, &filter.shufti) } +// pairPairConfirmBytes scans full 64-start blocks and returns the first +// fully confirmed anchor, or candidates when no full-block candidate matches. +// findUnicodePairConfirm establishes the feature and bound guards. +func pairPairConfirmBytes(s string, at, candidates int, filter *pairPairFilter, confirm unicodePairConfirm) (int, int) { + ptr := (*byte)(unsafe.Add(unsafe.Pointer(unsafe.StringData(s)), at)) + return pairPairConfirmVBMI64(ptr, candidates, &filter.vbmi, unsafe.StringData(string(confirm))) +} + func pairPairSkipBytes(s string, at int, filter *pairPairFilter) int { start := at offset := int(filter.offset) @@ -586,6 +623,26 @@ func tripleShuftiSkipBytes(s string, at int, filter *tripleShuftiFilter) int { // asciiPairAnchorSkipBytes scans a single bounded pair table. The route that // calls it has already proved an all-ASCII, non-NUL haystack; this function // remains a conservative filter and its caller replays plan transitions. +// rawByteMultiAnchorSkipBytes scans primary and tagged confirmation pairs in +// 64-byte VBMI blocks. Both paths return the conservative tag bits at the first +// surviving lane; tagsAt removes low-six-bit aliases before plan replay. +func rawByteMultiAnchorSkipBytes(s string, at int, filter *rawByteMultiAnchorFilter) (int, byte) { + start := at + remaining := len(s) - at + if filter.usable() && cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && cpu.X86.HasAVX512VBMI && + remaining >= 65+int(filter.maxConfirmOffset) { + full := ((remaining - 1 - int(filter.maxConfirmOffset)) / 64) * 64 + ptr := (*byte)(unsafe.Add(unsafe.Pointer(unsafe.StringData(s)), at)) + skipped, tags := rawByteMultiAnchorSkip64(ptr, remaining, filter) + at += skipped + if skipped < full { + return at - start, tags + } + } + skipped, tags := rawByteMultiAnchorSkipScalar(s, at, filter) + return at - start + skipped, tags +} + func asciiPairAnchorSkipBytes(s string, at int, filter *asciiPairAnchorFilter) int { start := at remaining := len(s) - at diff --git a/root_amd64.s b/root_amd64.s index 4a2649b..7d24520 100644 --- a/root_amd64.s +++ b/root_amd64.s @@ -189,6 +189,134 @@ literaldone64: VZEROUPPER RET +// literalSkipExact64 is the exact-byte specialization of literalSkip64. Fixed +// literal anchors need no fold vector. Eight unmasked memory-source compares +// keep independent cache lines in flight before the first ordered mask test. +TEXT ·literalSkipExact64(SB), NOSPLIT, $0-32 + MOVQ ptr+0(FP), AX + MOVQ n+8(FP), DX + MOVQ target+16(FP), CX + VPBROADCASTB CX, Z1 + MOVQ DX, R8 + SHRQ $9, R8 + JZ literalexactquad64 + +literalexactloop64: + VPCMPEQB (AX), Z1, K0 + VPCMPEQB 64(AX), Z1, K1 + VPCMPEQB 128(AX), Z1, K2 + VPCMPEQB 192(AX), Z1, K3 + VPCMPEQB 256(AX), Z1, K4 + VPCMPEQB 320(AX), Z1, K5 + VPCMPEQB 384(AX), Z1, K6 + VPCMPEQB 448(AX), Z1, K7 + KORTESTQ K0, K1 + JNE literalexactfirstpair64 + KORTESTQ K2, K3 + JNE literalexactsecondpair64 + KORTESTQ K4, K5 + JNE literalexactthirdpair64 + KORTESTQ K6, K7 + JNE literalexactfourthpair64 + ADDQ $512, AX + DECQ R8 + JNZ literalexactloop64 + ANDQ $511, DX + JMP literalexactquad64 + +literalexactfirstpair64: + KTESTQ K0, K0 + JNE literalexactblock064 + KMOVQ K1, CX + BSFQ CX, CX + ADDQ $64, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactsecondpair64: + KTESTQ K2, K2 + JNE literalexactblock264 + KMOVQ K3, CX + BSFQ CX, CX + ADDQ $192, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactthirdpair64: + KTESTQ K4, K4 + JNE literalexactblock464 + KMOVQ K5, CX + BSFQ CX, CX + ADDQ $320, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactfourthpair64: + KTESTQ K6, K6 + JNE literalexactblock664 + KMOVQ K7, CX + BSFQ CX, CX + ADDQ $448, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactblock064: + KMOVQ K0, CX + BSFQ CX, CX + ADDQ CX, AX + JMP literalexactdone64 +literalexactblock264: + KMOVQ K2, CX + BSFQ CX, CX + ADDQ $128, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactblock464: + KMOVQ K4, CX + BSFQ CX, CX + ADDQ $256, AX + ADDQ CX, AX + JMP literalexactdone64 +literalexactblock664: + KMOVQ K6, CX + BSFQ CX, CX + ADDQ $384, AX + ADDQ CX, AX + JMP literalexactdone64 + +literalexactquad64: + CMPQ DX, $256 + JL literalexactdouble64 + VPCMPEQB (AX), Z1, K0 + VPCMPEQB 64(AX), Z1, K1 + VPCMPEQB 128(AX), Z1, K2 + VPCMPEQB 192(AX), Z1, K3 + KORTESTQ K0, K1 + JNE literalexactfirstpair64 + KORTESTQ K2, K3 + JNE literalexactsecondpair64 + ADDQ $256, AX + SUBQ $256, DX + +literalexactdouble64: + CMPQ DX, $128 + JL literalexactsingle64 + VPCMPEQB (AX), Z1, K0 + VPCMPEQB 64(AX), Z1, K1 + KORTESTQ K0, K1 + JNE literalexactfirstpair64 + ADDQ $128, AX + SUBQ $128, DX + +literalexactsingle64: + CMPQ DX, $64 + JL literalexactdone64 + VPCMPEQB (AX), Z1, K0 + KTESTQ K0, K0 + JNE literalexactblock064 + ADDQ $64, AX +literalexactdone64: + SUBQ ptr+0(FP), AX + MOVQ AX, ret+24(FP) + VZEROUPPER + RET + // runMask32 returns one equality bit per byte for a repeated-token block. TEXT ·runMask32(SB), NOSPLIT, $0-28 MOVQ ptr+0(FP), AX @@ -2842,3 +2970,518 @@ pairpairvbmidone64: MOVQ BX, ret+24(FP) VZEROUPPER RET + +// pairPairConfirmVBMI64 keeps the pair-pair candidate mask in the AVX-512 +// loop and checks each set bit against the bounded raw-token representation. +// The packed confirmation has ten-byte parts: values at 0, 2, and 4, source +// offset at 6, width at 7, and value count at 8. Its anchor offset and vector +// part count are at 201 and 202 after its twenty slots. The pair-pair slots +// are excluded from that count after their UTF-8 byte classes make the VBMI +// low-six-bit table hits exact. +TEXT ·pairPairConfirmVBMI64(SB), NOSPLIT, $0-48 + MOVQ ptr+0(FP), AX + MOVQ n+8(FP), DX + MOVQ filter+16(FP), SI + MOVQ confirm+24(FP), DI + XORQ BX, BX + MOVQ $-1, CX + KMOVQ CX, K1 + VMOVDQU8 0(SI), K1, Z1 + VMOVDQU8 64(SI), K1, Z2 + VMOVDQU8 128(SI), K1, Z3 + VMOVDQU8 192(SI), K1, Z4 + MOVBLZX 256(SI), R8 + +pairpairconfirmdouble64: + CMPQ DX, $128 + JL pairpairconfirmsingle64 + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VMOVDQU8 (AX)(R8*1), K1, Z10 + VMOVDQU8 1(AX)(R8*1), K1, Z11 + VMOVDQU8 64(AX), K1, Z12 + VMOVDQU8 65(AX), K1, Z13 + VMOVDQU8 64(AX)(R8*1), K1, Z14 + VMOVDQU8 65(AX)(R8*1), K1, Z15 + + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPERMB Z3, Z10, Z10 + VPERMB Z4, Z11, Z11 + VPTESTMB Z9, Z0, K1, K2 + VPTESTMB Z11, Z10, K1, K3 + KANDQ K2, K3, K2 + + VPERMB Z1, Z12, Z12 + VPERMB Z2, Z13, Z13 + VPERMB Z3, Z14, Z14 + VPERMB Z4, Z15, Z15 + VPTESTMB Z13, Z12, K1, K3 + VPTESTMB Z15, Z14, K1, K4 + KANDQ K3, K4, K3 + KORTESTQ K2, K3 + JEQ pairpairconfirmadvance128 + + KMOVQ K2, CX + XORQ SI, SI + TESTQ CX, CX + JNZ pairpairconfirmcandidate + JMP pairpairconfirmsecond + +pairpairconfirmsecond: + MOVQ $1, SI + KMOVQ K3, CX + TESTQ CX, CX + JNZ pairpairconfirmcandidate + JMP pairpairconfirmadvance128 + +pairpairconfirmcandidate: + BSFQ CX, R9 + LEAQ (AX)(R9*1), R10 + CMPQ SI, $1 + JNE pairpairconfirmbase + ADDQ $64, R10 +pairpairconfirmbase: + MOVBLZX 201(DI), R13 + SUBQ R13, R10 + TESTB $2, 203(DI) + JNE pairpairconfirmvariable + LEAQ (R10)(R13*1), R11 + MOVQ $0x80C0, R14 + MOVWQZX (R11), R12 + ANDQ $0xC0C0, R12 + CMPQ R14, R12 + JNE pairpairconfirmreject + MOVWQZX (R11)(R8*1), R12 + ANDQ $0xC0C0, R12 + CMPQ R14, R12 + JNE pairpairconfirmreject + MOVQ DI, R11 + MOVBLZX 202(DI), R12 + TESTQ R12, R12 + JZ pairpairconfirmaccepted +pairpairconfirmpart: + MOVBLZX 6(R11), R13 + MOVBLZX 7(R11), R14 + CMPQ R14, $2 + JEQ pairpairconfirmword + MOVBLZX (R10)(R13*1), R14 + JMP pairpairconfirmvalue +pairpairconfirmword: + MOVWQZX (R10)(R13*1), R14 +pairpairconfirmvalue: + MOVWQZX 0(R11), R15 + CMPQ R14, R15 + JEQ pairpairconfirmnext + CMPB 8(R11), $2 + JL pairpairconfirmreject + MOVWQZX 2(R11), R15 + CMPQ R14, R15 + JEQ pairpairconfirmnext + CMPB 8(R11), $3 + JNE pairpairconfirmreject + MOVWQZX 4(R11), R15 + CMPQ R14, R15 + JNE pairpairconfirmreject +pairpairconfirmnext: + ADDQ $10, R11 + DECQ R12 + JNZ pairpairconfirmpart + JMP pairpairconfirmaccepted + +// Variable-width confirmation walks the raw forms in source order. Each +// ten-byte part contains up to three zero-padded three-byte forms and a count +// at byte nine. A form's UTF-8 lead byte determines whether the cursor advances +// by one, two, or three bytes. +pairpairconfirmvariable: + MOVQ R10, R13 + MOVQ DI, R11 + MOVBLZX 202(DI), R12 +pairpairconfirmvariablepart: + MOVBLZX 9(R11), R14 + MOVQ R11, R15 +pairpairconfirmvariableform: + MOVBLZX 0(R15), R10 + CMPB 0(R13), R10 + JNE pairpairconfirmvariablenextform + CMPQ R10, $0x80 + JL pairpairconfirmvariableone + MOVBLZX 1(R15), R10 + CMPB 1(R13), R10 + JNE pairpairconfirmvariablenextform + MOVBLZX 0(R15), R10 + CMPQ R10, $0xe0 + JL pairpairconfirmvariabletwo + MOVBLZX 2(R15), R10 + CMPB 2(R13), R10 + JNE pairpairconfirmvariablenextform + ADDQ $3, R13 + JMP pairpairconfirmvariablenextpart +pairpairconfirmvariabletwo: + ADDQ $2, R13 + JMP pairpairconfirmvariablenextpart +pairpairconfirmvariableone: + INCQ R13 +pairpairconfirmvariablenextpart: + ADDQ $10, R11 + DECQ R12 + JNZ pairpairconfirmvariablepart + LEAQ (AX)(R9*1), R10 + CMPQ SI, $1 + JNE pairpairconfirmvariablewidth + ADDQ $64, R10 +pairpairconfirmvariablewidth: + MOVBLZX 201(DI), R12 + SUBQ R12, R10 + SUBQ R10, R13 + JMP pairpairconfirmreturnaccepted +pairpairconfirmvariablenextform: + ADDQ $3, R15 + DECQ R14 + JNZ pairpairconfirmvariableform + JMP pairpairconfirmreject +pairpairconfirmaccepted: + MOVBLZX 200(DI), R13 +pairpairconfirmreturnaccepted: + ADDQ R9, BX + CMPQ SI, $1 + JNE pairpairconfirmdone + ADDQ $64, BX + JMP pairpairconfirmdone + +pairpairconfirmreject: + BTRQ R9, CX + TESTQ CX, CX + JNZ pairpairconfirmcandidate + CMPQ SI, $0 + JEQ pairpairconfirmsecond + CMPQ SI, $1 + JEQ pairpairconfirmadvance128 + JMP pairpairconfirmadvance64 + +pairpairconfirmadvance128: + ADDQ $128, AX + ADDQ $128, BX + SUBQ $128, DX + JMP pairpairconfirmdouble64 + +pairpairconfirmsingle64: + CMPQ DX, $64 + JL pairpairconfirmdone + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VMOVDQU8 (AX)(R8*1), K1, Z10 + VMOVDQU8 1(AX)(R8*1), K1, Z11 + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPERMB Z3, Z10, Z10 + VPERMB Z4, Z11, Z11 + VPTESTMB Z9, Z0, K1, K2 + VPTESTMB Z11, Z10, K1, K3 + KANDQ K2, K3, K2 + KTESTQ K2, K2 + JEQ pairpairconfirmadvance64 + KMOVQ K2, CX + MOVQ $2, SI + JMP pairpairconfirmcandidate + +pairpairconfirmadvance64: + ADDQ $64, AX + ADDQ $64, BX + SUBQ $64, DX + JMP pairpairconfirmsingle64 + +pairpairconfirmdone: + MOVQ n+8(FP), R12 + CMPQ BX, R12 + JNE pairpairconfirmwidthdone + XORQ R13, R13 +pairpairconfirmwidthdone: + MOVQ BX, ret+32(FP) + MOVQ R13, width+40(FP) + VZEROUPPER + RET + +// rawByteMultiAnchorSkip64 intersects a primary pattern-tag pair with up to +// three fixed-displacement confirmation pairs. Tables use VPERMB's low six +// source bits. It returns the surviving tag byte with the first lane; Go then +// checks exact primary, confirmation, and guard pairs only for those tags. +// rawByteMultiAnchorFilter lays out primary tables at 0/64, confirmation-first +// tables at 128/192/256, and confirmation-second tables at 320/384/448. +TEXT ·rawByteMultiAnchorSkip64(SB), NOSPLIT, $64-33 + MOVQ ptr+0(FP), AX + MOVQ n+8(FP), DX + MOVQ filter+16(FP), SI + MOVQ $-1, CX + XORL R15, R15 + KMOVQ CX, K1 + VMOVDQU8 0(SI), K1, Z1 + VMOVDQU8 64(SI), K1, Z2 + VMOVDQU8 128(SI), K1, Z3 + VMOVDQU8 192(SI), K1, Z4 + VMOVDQU8 256(SI), K1, Z5 + VMOVDQU8 320(SI), K1, Z6 + VMOVDQU8 384(SI), K1, Z7 + VMOVDQU8 448(SI), K1, Z8 + MOVBLZX 512(SI), R8 + MOVBLZX 513(SI), R9 + MOVBLZX 514(SI), R10 + MOVBLZX 516(SI), R11 + ADDQ $65, R11 + LEAQ 192(R11), R12 + // The eight-block zero scan reads the adjacent primary byte through offset + // 512. Keep a complete confirmation horizon for every scanned block too: + // an aggregate hit must safely replay the four-/one-block dispatcher. + LEAQ 448(R11), BX +rawbytemultianchorloop64: + CMPQ DX, R11 + JL rawbytemultianchordone64 + CMPQ DX, BX + JGE rawbytemultianchorzero512 +rawbytemultianchorfour64: + CMPQ DX, R12 + JL rawbytemultianchorsingle64 + + // Four independent primary blocks hide VPERMB latency on no-candidate text. + // Materialize their tag products, then reduce them once. The common sparse + // no-hit path crosses only one byte mask; the per-block masks are derived + // only when the aggregate is nonzero and are then reused for density choice. + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VMOVDQU8 64(AX), K1, Z10 + VMOVDQU8 65(AX), K1, Z11 + VMOVDQU8 128(AX), K1, Z12 + VMOVDQU8 129(AX), K1, Z13 + VMOVDQU8 192(AX), K1, Z14 + VMOVDQU8 193(AX), K1, Z15 + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPERMB Z1, Z10, Z10 + VPERMB Z2, Z11, Z11 + VPERMB Z1, Z12, Z12 + VPERMB Z2, Z13, Z13 + VPERMB Z1, Z14, Z14 + VPERMB Z2, Z15, Z15 + VPANDQ Z9, Z0, K1, Z0 + VPANDQ Z11, Z10, K1, Z10 + VPANDQ Z13, Z12, K1, Z12 + VPANDQ Z15, Z14, K1, Z14 + VPORQ Z10, Z0, K1, Z9 + // 0xfe is the three-input OR truth table. Z9 already carries blocks 0|1. + VPTERNLOGD $0xfe, Z14, Z12, K1, Z9 + VPTESTMB Z9, Z9, K1, K2 + KTESTQ K2, K2 + JEQ rawbytemultianchoradvance256 + + // An aggregate hit is rare on sparse data. Only then recover the individual + // masks needed to select a sole block or enter the dense schedule. + VPTESTMB Z0, Z0, K1, K2 + VPTESTMB Z10, Z10, K1, K3 + VPTESTMB Z12, Z12, K1, K4 + VPTESTMB Z14, Z14, K1, K5 + // Any two occupied blocks choose the bounded dense one-block schedule; a + // sole occupied block keeps its already materialized primary product. + KORTESTQ K2, K3 + JNE rawbytemultianchorfirstnonzero64 + KORTESTQ K4, K5 + JNE rawbytemultianchorlastnonzero64 +rawbytemultianchoradvance256: + ADDQ $256, AX + SUBQ $256, DX + JMP rawbytemultianchorloop64 +rawbytemultianchorfirstnonzero64: + KORTESTQ K4, K5 + JNE rawbytemultianchordense64 + KTESTQ K2, K2 + JEQ rawbytemultianchorblock164 + KTESTQ K3, K3 + JNE rawbytemultianchordense64 + JMP rawbytemultianchorconfirm64 +rawbytemultianchorlastnonzero64: + KTESTQ K4, K4 + JEQ rawbytemultianchorblock364 + KTESTQ K5, K5 + JNE rawbytemultianchordense64 +rawbytemultianchorblock264: + VMOVDQA64 Z12, K1, Z0 + ADDQ $128, AX + SUBQ $128, DX + JMP rawbytemultianchorconfirm64 +rawbytemultianchorblock164: + VMOVDQA64 Z10, K1, Z0 + ADDQ $64, AX + SUBQ $64, DX + JMP rawbytemultianchorconfirm64 +rawbytemultianchorblock364: + VMOVDQA64 Z14, K1, Z0 + ADDQ $192, AX + SUBQ $192, DX + JMP rawbytemultianchorconfirm64 + +// The sparse fast path has no candidate ordering work: it only proves that +// eight independent 64-byte primary blocks are all zero. Any aggregate hit +// replays the existing four-block dispatcher at the unchanged AX/DX, where it +// recovers masks, preserves leftmost order, and applies the density switch. +rawbytemultianchorzero512: + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VMOVDQU8 64(AX), K1, Z10 + VMOVDQU8 65(AX), K1, Z11 + VMOVDQU8 128(AX), K1, Z12 + VMOVDQU8 129(AX), K1, Z13 + VMOVDQU8 192(AX), K1, Z14 + VMOVDQU8 193(AX), K1, Z15 + VMOVDQU8 256(AX), K1, Z16 + VMOVDQU8 257(AX), K1, Z17 + VMOVDQU8 320(AX), K1, Z18 + VMOVDQU8 321(AX), K1, Z19 + VMOVDQU8 384(AX), K1, Z20 + VMOVDQU8 385(AX), K1, Z21 + VMOVDQU8 448(AX), K1, Z22 + VMOVDQU8 449(AX), K1, Z23 + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPERMB Z1, Z10, Z10 + VPERMB Z2, Z11, Z11 + VPERMB Z1, Z12, Z12 + VPERMB Z2, Z13, Z13 + VPERMB Z1, Z14, Z14 + VPERMB Z2, Z15, Z15 + VPERMB Z1, Z16, Z16 + VPERMB Z2, Z17, Z17 + VPERMB Z1, Z18, Z18 + VPERMB Z2, Z19, Z19 + VPERMB Z1, Z20, Z20 + VPERMB Z2, Z21, Z21 + VPERMB Z1, Z22, Z22 + VPERMB Z2, Z23, Z23 + VPANDQ Z9, Z0, K1, Z0 + VPANDQ Z11, Z10, K1, Z10 + VPANDQ Z13, Z12, K1, Z12 + VPANDQ Z15, Z14, K1, Z14 + VPANDQ Z17, Z16, K1, Z16 + VPANDQ Z19, Z18, K1, Z18 + VPANDQ Z21, Z20, K1, Z20 + VPANDQ Z23, Z22, K1, Z22 + // Reduce eight products in four Boolean operations. Each 0xfe ternary + // instruction ORs its two sources with its old destination. + VPTERNLOGD $0xfe, Z12, Z10, K1, Z0 + VPTERNLOGD $0xfe, Z18, Z16, K1, Z14 + VPTERNLOGD $0xfe, Z20, Z14, K1, Z0 + VPORQ Z22, Z0, K1, Z0 + VPTESTMB Z0, Z0, K1, K2 + KTESTQ K2, K2 + JNE rawbytemultianchorfour64 + ADDQ $512, AX + SUBQ $512, DX + JMP rawbytemultianchorloop64 + +rawbytemultianchorsingle64: + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPTESTMB Z9, Z0, K1, K2 + KTESTQ K2, K2 + JEQ rawbytemultianchoradvance64 + VPANDQ Z9, Z0, K1, Z0 + +rawbytemultianchorconfirm64: + // Do not pay the three confirmation lookups for a block with no primary + // tag. A primary hit remains conservative; the exact Go checks still decide + // the candidate before the common raw transition replay. + VMOVDQU8 0(AX)(R8*1), K1, Z9 + VMOVDQU8 1(AX)(R8*1), K1, Z10 + VMOVDQU8 0(AX)(R9*1), K1, Z11 + VMOVDQU8 1(AX)(R9*1), K1, Z12 + VMOVDQU8 0(AX)(R10*1), K1, Z13 + VMOVDQU8 1(AX)(R10*1), K1, Z14 + VPERMB Z3, Z9, Z9 + VPERMB Z6, Z10, Z10 + VPERMB Z4, Z11, Z11 + VPERMB Z7, Z12, Z12 + VPERMB Z5, Z13, Z13 + VPERMB Z8, Z14, Z14 + VPANDQ Z10, Z9, K1, Z9 + VPANDQ Z12, Z11, K1, Z11 + VPANDQ Z14, Z13, K1, Z13 + VPANDQ Z9, Z0, K1, Z9 + VPANDQ Z11, Z0, K1, Z11 + VPANDQ Z13, Z0, K1, Z13 + VPORQ Z11, Z9, K1, Z9 + VPORQ Z13, Z9, K1, Z9 + VPTESTMB Z9, Z9, K1, K2 + KTESTQ K2, K2 + JNE rawbytemultianchorstop64 +rawbytemultianchoradvance64: + ADDQ $64, AX + SUBQ $64, DX + JMP rawbytemultianchorloop64 +rawbytemultianchorstop64: + KMOVQ K2, CX + BSFQ CX, CX + VMOVDQU8 Z9, (SP) + MOVBLZX (SP)(CX*1), R15 + ADDQ CX, AX + JMP rawbytemultianchordone64 +// The dense body is the proven one-block primary-plus-confirmation schedule. +// It changes only batching; the same conservative tables and Go replay remain +// the match authority. +rawbytemultianchordense64: + // A dense-prefix/sparse-suffix diagnostic is three times slower when dense + // mode owns the whole input. Bound a dense epoch to 4 KiB, or to the + // remaining safe block count. The decrement below replaces the old per-block + // tail comparison; expiration re-enters the shared four-block dispatcher. + CMPQ DX, R11 + JL rawbytemultianchordone64 + MOVQ DX, R13 + SUBQ R11, R13 + SHRQ $6, R13 + INCQ R13 + CMPQ R13, $64 + JLE rawbytemultianchordenseloop64 + MOVQ $64, R13 +rawbytemultianchordenseloop64: + VMOVDQU8 (AX), K1, Z0 + VMOVDQU8 1(AX), K1, Z9 + VMOVDQU8 0(AX)(R8*1), K1, Z10 + VMOVDQU8 1(AX)(R8*1), K1, Z11 + VMOVDQU8 0(AX)(R9*1), K1, Z12 + VMOVDQU8 1(AX)(R9*1), K1, Z13 + VMOVDQU8 0(AX)(R10*1), K1, Z14 + VMOVDQU8 1(AX)(R10*1), K1, Z15 + VPERMB Z1, Z0, Z0 + VPERMB Z2, Z9, Z9 + VPERMB Z3, Z10, Z10 + VPERMB Z6, Z11, Z11 + VPERMB Z4, Z12, Z12 + VPERMB Z7, Z13, Z13 + VPERMB Z5, Z14, Z14 + VPERMB Z8, Z15, Z15 + VPANDQ Z9, Z0, K1, Z0 + VPANDQ Z11, Z10, K1, Z10 + VPANDQ Z13, Z12, K1, Z12 + VPANDQ Z15, Z14, K1, Z14 + VPANDQ Z10, Z0, K1, Z10 + VPANDQ Z12, Z0, K1, Z12 + VPANDQ Z14, Z0, K1, Z14 + VPORQ Z12, Z10, K1, Z10 + VPORQ Z14, Z10, K1, Z10 + VPTESTMB Z10, Z10, K1, K2 + KTESTQ K2, K2 + JNE rawbytemultianchordensestop64 + ADDQ $64, AX + SUBQ $64, DX + DECQ R13 + JNE rawbytemultianchordenseloop64 + JMP rawbytemultianchorloop64 +rawbytemultianchordensestop64: + VMOVDQA64 Z10, K1, Z9 + JMP rawbytemultianchorstop64 + +rawbytemultianchordone64: + SUBQ ptr+0(FP), AX + MOVQ AX, ret+24(FP) + MOVB R15, tags+32(FP) + VZEROUPPER + RET diff --git a/root_amd64_bench_test.go b/root_amd64_bench_test.go new file mode 100644 index 0000000..0b9bffe --- /dev/null +++ b/root_amd64_bench_test.go @@ -0,0 +1,32 @@ +//go:build amd64 && go1.24 + +package casei + +import ( + "bytes" + "strings" + "testing" + "unsafe" + + "golang.org/x/sys/cpu" +) + +func BenchmarkLiteralSkipExactCeiling(b *testing.B) { + if !cpu.X86.HasAVX512F || !cpu.X86.HasAVX512BW { + b.Skip("AVX-512 BW exact-byte path is disabled") + } + input := []byte(strings.Repeat("x", 5<<20)) + target := uint64(' ') * byteOnes + b.Run("candidate", func(b *testing.B) { + b.SetBytes(int64(len(input))) + for b.Loop() { + _ = literalSkipExact64(unsafe.SliceData(input), len(input), target) + } + }) + b.Run("index_byte", func(b *testing.B) { + b.SetBytes(int64(len(input))) + for b.Loop() { + _ = bytes.IndexByte(input, ' ') + } + }) +} diff --git a/root_amd64_test.go b/root_amd64_test.go index 40d90a8..5b9a669 100644 --- a/root_amd64_test.go +++ b/root_amd64_test.go @@ -3,6 +3,7 @@ package casei import ( + "bytes" "strings" "testing" "unsafe" @@ -10,6 +11,41 @@ import ( "golang.org/x/sys/cpu" ) +func TestLiteralSkipExact64MatchesModel(t *testing.T) { + if !cpu.X86.HasAVX512F || !cpu.X86.HasAVX512BW { + t.Skip("AVX-512 BW exact-byte path is disabled") + } + target := uint64(' ') * byteOnes + check := func(input []byte, n int) { + t.Helper() + full := n &^ 63 + want := bytes.IndexByte(input[:full], ' ') + if want < 0 { + want = full + } + if got := literalSkipExact64(unsafe.SliceData(input), n, target); got != want { + t.Fatalf("n=%d: skip=%d want=%d", n, got, want) + } + } + lengths := []int{0, 1, 63, 64, 65, 127, 128, 129, 255, 256, 257, 511, 512, 513, 1023, 1024, 1025, 4095} + positions := []int{0, 1, 63, 64, 127, 128, 191, 192, 255, 256, 319, 320, 383, 384, 447, 448, 511, 512, 1023, 4094} + for _, n := range lengths { + for _, alignment := range []int{0, 1, 31, 63} { + backing := []byte(strings.Repeat("x", alignment+n+64)) + input := backing[alignment : alignment+n] + check(input, n) + for _, at := range positions { + if at >= n { + continue + } + input[at] = ' ' + check(input, n) + input[at] = 'x' + } + } + } +} + func TestPairSetSkip(t *testing.T) { filter := rootFilter{ pairs: [16]rootPair{ diff --git a/root_bench_test.go b/root_bench_test.go index 588e893..23cc46b 100644 --- a/root_bench_test.go +++ b/root_bench_test.go @@ -35,6 +35,166 @@ func BenchmarkPairShuftiMatcher(b *testing.B) { } } +var ( + rawByteBenchmarkMatch Match + rawByteBenchmarkOK bool +) + +// BenchmarkRawByteConstruction keeps plan construction and its first ordinary +// Find in one operation. It catches a cache-sized raw transition allocation on +// one-shot Matchers and separately measures raw publication plus its first use, +// all through the same public route as the density sweep. +func BenchmarkRawByteConstruction(b *testing.B) { + for _, tc := range []struct { + name string + patterns []string + haystack string + rawInstallAndFirstUse bool + }{ + {"two_patterns_512B", rawByteCyrillicPatterns[:2], rawByteFalseCandidates(4, 128), false}, + {"two_patterns_4KiB", rawByteCyrillicPatterns[:2], rawByteFalseCandidates(4, 1024), false}, + {"five_patterns_512B", rawByteCyrillicPatterns, rawByteFalseCandidates(4, 128), false}, + {"five_patterns_513B_zero_admission", rawByteCyrillicPatterns, strings.Repeat("x", 513), false}, + {"five_patterns_5MiB_raw_install_and_first_use", rawByteCyrillicPatterns, rawByteFalseCandidatesAtLeast(256, rawBytePublicationCorpusBytes), true}, + {"two_shared_100_units_1KiB_zero_admission", rawByteLongPrefixPatterns(), strings.Repeat("x", 1<<10), false}, + {"two_mixed_folded_ascii_root_1KiB", []string{"Д", "xД"}, strings.Repeat("x", 1<<10), false}, + } { + b.Run(tc.name, func(b *testing.B) { + bytes := len(tc.haystack) + if tc.rawInstallAndFirstUse { + bytes *= 3 + } + b.SetBytes(int64(bytes)) + b.ReportAllocs() + for b.Loop() { + matcher := NewMatcher(tc.patterns) + if got, ok := matcher.Find(tc.haystack); ok || got != (Match{}) { + b.Fatalf("false-candidate stream matched: %+v,%t", got, ok) + } + if tc.rawInstallAndFirstUse { + // Keep decoded admission, the next reuse, and one following reuse in + // one operation. An implementation may publish an eligible acceleration + // between those calls, but both source arms execute the same public work. + for range 2 { + if got, ok := matcher.Find(tc.haystack); ok || got != (Match{}) { + b.Fatalf("raw install/first use stream matched: %+v,%t", got, ok) + } + } + } + } + }) + } +} + +// BenchmarkRawByteDensity measures false-root streams through the public +// Matcher.Find entry point. The baseline advances decoded units; an eligible +// compiled plan may replace that transition with its raw row without changing +// this workload. +func BenchmarkRawByteDensity(b *testing.B) { + for _, tc := range []struct { + name string + patterns []string + haystack string + }{ + {"two_4KiB_one_in_32", rawByteCyrillicPatterns[:2], rawByteFalseCandidates(32, 4096/32)}, + {"two_4KiB_zero_admission", rawByteCyrillicPatterns[:2], strings.Repeat("x", 4<<10)}, + {"five_one_in_64", rawByteCyrillicPatterns, rawByteFalseCandidatesAtLeast(64, rawByteBenchmarkCorpusBytes)}, + {"five_one_in_4", rawByteCyrillicPatterns, rawByteFalseCandidatesAtLeast(4, rawByteBenchmarkCorpusBytes/16)}, + } { + matcher := NewMatcher(tc.patterns) + b.Run(tc.name, func(b *testing.B) { + b.SetBytes(int64(len(tc.haystack))) + b.ReportAllocs() + if got, ok := matcher.Find(tc.haystack); ok || got != (Match{}) { + b.Fatalf("false-candidate stream matched: %+v,%t", got, ok) + } + // The construction benchmark owns the first-call crossover. This + // benchmark measures a reused public Matcher, so complete its second + // ordinary Find before the timed steady-state loop. + if got, ok := matcher.Find(tc.haystack); ok || got != (Match{}) { + b.Fatalf("false-candidate stream matched: %+v,%t", got, ok) + } + b.ResetTimer() + for b.Loop() { + rawByteBenchmarkMatch, rawByteBenchmarkOK = matcher.Find(tc.haystack) + } + }) + } +} + +// BenchmarkRawByteFreshFind measures one ordinary Find on a new Matcher. It +// includes every setup cost that this call pays. The long miss, near miss, +// sparse miss, clustered miss, and early answer keep the decision boundary +// visible to both sides of a comparison. +func BenchmarkRawByteFreshFind(b *testing.B) { + longMiss := rawByteFalseCandidatesAtLeast(256, 10<<20) + longNearMiss := rawByteNearMissCandidatesAtLeast(256, rawBytePublicationCorpusBytes) + longSparse := rawByteFalseCandidatesAtLeast(8192, rawBytePublicationCorpusBytes) + longClustered := rawByteFalseCandidates(64, rawByteFreshSampleBytes/64) + + strings.Repeat("x", rawBytePublicationCorpusBytes-rawByteFreshSampleBytes) + longLateMatch, longLateMatchStart := rawByteLateMatchCandidatesAtLeast(256, 10<<20) + longEarlyMatch, longEarlyMatchStart := rawByteEarlyMatchCandidatesAtLeast(256, rawBytePublicationCorpusBytes, 8<<10) + for _, tc := range []struct { + name string + haystack string + want Match + wantOK bool + }{ + {"five_long_false_one_in_256", longMiss, Match{}, false}, + {"five_long_near_miss_one_in_256", longNearMiss, Match{}, false}, + {"five_long_sparse_one_in_8192", longSparse, Match{}, false}, + {"five_long_clustered", longClustered, Match{}, false}, + {"five_long_early_match_one_in_256", longEarlyMatch, Match{Pattern: 0, Start: longEarlyMatchStart}, true}, + {"five_long_late_match_one_in_256", longLateMatch, Match{Pattern: 0, Start: longLateMatchStart}, true}, + } { + b.Run(tc.name, func(b *testing.B) { + b.SetBytes(int64(len(tc.haystack))) + b.ReportAllocs() + for b.Loop() { + matcher := NewMatcher(rawByteCyrillicPatterns) + got, gotOK := matcher.Find(tc.haystack) + if gotOK != tc.wantOK || got != tc.want { + b.Fatalf("fresh Find = %+v,%t; want %+v,%t", got, gotOK, tc.want, tc.wantOK) + } + } + }) + } +} + +// BenchmarkRawByteFindAfterFreshFind measures a second Find after the same +// Matcher has completed a long fresh no-match search. The setup is deliberately +// outside the timer: the fresh benchmark owns its cost, while this benchmark +// keeps the published-view reuse state comparable across both source arms. +func BenchmarkRawByteFindAfterFreshFind(b *testing.B) { + publication := rawByteFalseCandidatesAtLeast(256, 10<<20) + lateMatch, lateMatchStart := rawByteLateMatchCandidatesAtLeast(256, rawBytePublicationCorpusBytes) + for _, tc := range []struct { + name string + haystack string + want Match + wantOK bool + }{ + {"five_long_reused_near_miss_one_in_256", rawByteNearMissCandidatesAtLeast(256, rawBytePublicationCorpusBytes), Match{}, false}, + {"five_long_reused_late_match_one_in_256", lateMatch, Match{Pattern: 0, Start: lateMatchStart}, true}, + } { + b.Run(tc.name, func(b *testing.B) { + matcher := NewMatcher(rawByteCyrillicPatterns) + if got, ok := matcher.Find(publication); ok || got != (Match{}) { + b.Fatalf("publication Find = %+v,%t", got, ok) + } + b.SetBytes(int64(len(tc.haystack))) + b.ReportAllocs() + b.ResetTimer() + for b.Loop() { + got, gotOK := matcher.Find(tc.haystack) + if gotOK != tc.wantOK || got != tc.want { + b.Fatalf("reused Find = %+v,%t; want %+v,%t", got, gotOK, tc.want, tc.wantOK) + } + } + }) + } +} + func BenchmarkTripleSkipBytes(b *testing.B) { plan := newSearchPlan([]string{"fatal panic", "segfault detected"}) haystack := strings.Repeat("x", 1<<20) diff --git a/root_other.go b/root_other.go index 99eef15..95259c9 100644 --- a/root_other.go +++ b/root_other.go @@ -8,6 +8,8 @@ func runtimeVectorBits() int { return 0 } func asciiPairVBMIEnabled() bool { return false } +func unicodePairConfirmVectorEnabled() bool { return false } + func asciiFixedPrefix8(s string, at int, word, fold uint64) bool { for i := 0; i < 8; i++ { if s[at+i]|byte(fold>>(8*i)) != byte(word>>(8*i)) { @@ -62,6 +64,10 @@ func literalSkipASCII(s string, at int, kind uint8, needle byte) int { return at - start } +func literalSkipExactASCII(s string, at int, needle byte) int { + return literalSkipASCII(s, at, rootExact, needle) +} + func probeSkipBytes(s string, at, candidates int, probe *asciiProbe) int { start := at for at-start < candidates { @@ -139,6 +145,19 @@ func pairShuftiSkipBytes(s string, at int, filter *rootFilter) int { return pairShuftiSkipScalar(s, at, &filter.shufti) } +func pairPairConfirmBytes(s string, at, candidates int, filter *pairPairFilter, confirm unicodePairConfirm) (int, int) { + start := at + for at-start < candidates { + if pairPairAt(s, at, filter) { + if width, ok := confirm.matchWidthAt(s, at-confirm.anchorAt()); ok { + return at - start, width + } + } + at++ + } + return candidates, 0 +} + func pairPairSkipBytes(s string, at int, filter *pairPairFilter) int { start := at for at+int(filter.offset)+1 < len(s) { @@ -222,6 +241,10 @@ func tripleShuftiSkipBytes(s string, at int, filter *tripleShuftiFilter) int { return tripleShuftiSkipScalar(s, at, filter) } +func rawByteMultiAnchorSkipBytes(s string, at int, filter *rawByteMultiAnchorFilter) (int, byte) { + return rawByteMultiAnchorSkipScalar(s, at, filter) +} + func asciiPairAnchorSkipBytes(s string, at int, filter *asciiPairAnchorFilter) int { return asciiPairAnchorSkipScalar(s, at, filter) } diff --git a/root_test.go b/root_test.go index c7c5963..62d7b39 100644 --- a/root_test.go +++ b/root_test.go @@ -755,22 +755,173 @@ func TestPairPairVBMIProjection(t *testing.T) { } } - // The byte projection may reach an alias, but the ordinary Unicode matcher - // must reject it and continue through the later exact rendering. - alias := []byte(strings.Repeat("x", int(filter.offset)+2)) - alias[0], alias[1] = filter.first0^0x40, filter.second0^0x40 - alias[filter.offset], alias[filter.offset+1] = filter.confirmFirst0^0x40, filter.confirmSecond0^0x40 - const gap = 64 - haystack := string(alias) + strings.Repeat("x", gap) + "ЯР" - want := len(alias) + gap - if cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && cpu.X86.HasAVX512VBMI { - if got := pairPairSkipBytes(haystack, 0, filter); got != 0 { - t.Fatalf("VBMI pair alias did not reach replay: skip=%d", got) + // The byte projection may reach either high-bit alias, but the fused and + // decoded Unicode matchers must reject it and continue to the exact form. + for _, aliasBit := range []byte{0x40, 0x80} { + alias := []byte(strings.Repeat("x", int(filter.offset)+2)) + alias[0], alias[1] = filter.first0^aliasBit, filter.second0^aliasBit + alias[filter.offset], alias[filter.offset+1] = filter.confirmFirst0^aliasBit, filter.confirmSecond0^aliasBit + const gap = 4096 + haystack := string(alias) + strings.Repeat("x", gap) + "ЯР" + want := len(alias) + gap + if cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && cpu.X86.HasAVX512VBMI { + if got := pairPairSkipBytes(haystack, 0, filter); got != 0 { + t.Fatalf("VBMI pair alias %#x did not reach replay: skip=%d", aliasBit, got) + } + } + match, ok := plan.find(haystack) + if !ok || match != (Match{Pattern: 0, Start: want}) { + t.Fatalf("VBMI pair alias %#x hid exact match: Find=%+v,%t want start %d", aliasBit, match, ok, want) } } - match, ok := plan.find(haystack) - if !ok || match != (Match{Pattern: 0, Start: want}) { - t.Fatalf("VBMI pair alias hid exact match: Find=%+v,%t want start %d", match, ok, want) +} + +func TestUnicodePairConfirm(t *testing.T) { + if unicodePairConfirmPartSize != 10 || unicodePairConfirmMaxLengthAt != 200 || + unicodePairConfirmAnchorAt != 201 || unicodePairConfirmNAt != 202 || + unicodePairConfirmPackedSize != 204 { + t.Fatalf("unexpected packed confirmation layout: part=%d length=%d anchor=%d n=%d size=%d", + unicodePairConfirmPartSize, unicodePairConfirmMaxLengthAt, unicodePairConfirmAnchorAt, + unicodePairConfirmNAt, unicodePairConfirmPackedSize) + } + + const needle = "приключения лилий" + plan := newSearchPlan([]string{needle}) + confirm := plan.unicodePairConfirm() + if plan.unicodePairN == 0 || plan.unicodePairs[0].pairPair.valid == 0 || !confirm.valid() { + t.Fatalf("no bounded Unicode confirmation: anchors=%+v confirm=%+v", plan.unicodePairs, confirm) + } + if got, want := confirm.maxLength(), len(needle); got != want { + t.Fatalf("confirmation length = %d, want %d", got, want) + } + if got, want := confirm.anchorAt(), plan.unicodePairs[0].at; got != want { + t.Fatalf("confirmation anchor = %d, want %d", got, want) + } + if got := confirm.skippedN(); got != unicodePairConfirmSkippedParts { + t.Fatalf("pair-pair-confirmed parts = %d, want %d", got, unicodePairConfirmSkippedParts) + } + asciiPlan := newSearchPlan([]string{"ascii literal"}) + if !asciiPlan.asciiOnly || asciiPlan.singlePayload != "ascii literal" || asciiPlan.unicodePairConfirm().valid() { + t.Fatalf("all-ASCII payload was not kept separate: asciiOnly=%t payload=%q confirm=%+v", + asciiPlan.asciiOnly, asciiPlan.singlePayload, asciiPlan.unicodePairConfirm()) + } + + for _, rendering := range []string{needle, strings.ToUpper(needle)} { + if _, ok := confirm.matchWidthAt(rendering, 0); !ok || !plan.matchesSingleAt(rendering, 0) { + t.Fatalf("confirmation rejected simple-fold rendering %q", rendering) + } + } + nearMiss := needle[:len(needle)-len("й")] + "я" + if _, ok := confirm.matchWidthAt(nearMiss, 0); ok || plan.matchesSingleAt(nearMiss, 0) { + t.Fatalf("confirmation accepted near miss %q", nearMiss) + } + for _, nearMiss := range []string{ + "я" + needle[len("п"):], + needle[:len("п")] + "я" + needle[len("п")+len("р"):], + } { + if _, ok := confirm.matchWidthAt(nearMiss, 0); ok { + t.Fatalf("confirmation accepted pair-pair near miss %q", nearMiss) + } + } + + check := func(t *testing.T, haystack string) { + t.Helper() + got, gotOK := plan.find(haystack) + want := reference(haystack, needle) + if want < 0 { + if gotOK || got != (Match{}) { + t.Fatalf("Find = %+v,%t want no match", got, gotOK) + } + return + } + if !gotOK || got != (Match{Pattern: 0, Start: want}) { + t.Fatalf("Find = %+v,%t want start %d", got, gotOK, want) + } + } + for _, offset := range []int{0, 1, 63, 64, 127, 128, 4095} { + for _, rendering := range []string{needle, strings.ToUpper(needle)} { + check(t, strings.Repeat("x", offset)+rendering+strings.Repeat("x", 4096)) + } + check(t, strings.Repeat("x", offset)+nearMiss+strings.Repeat("x", 4096)) + } + // Both candidates occupy one 64-start vector block. The first is rejected + // by the final token, so the kernel must continue to the later exact one. + check(t, strings.Repeat("x", 64)+nearMiss+"x"+strings.ToUpper(needle)+strings.Repeat("x", 4096)) + // The final valid start is outside a complete vector block and stays on the + // bounded scalar tail. + check(t, strings.Repeat("x", 4096)+strings.ToUpper(needle)) + + // The byte-pair anchor need not be the first token. Its coordinate is + // translated back to the literal start inside the vector kernel. + prefixedNeedle := "x" + needle + prefixedPlan := newSearchPlan([]string{prefixedNeedle}) + prefixedConfirm := prefixedPlan.unicodePairConfirm() + if !prefixedConfirm.valid() || prefixedConfirm.anchorAt() != prefixedPlan.unicodePairs[0].at || + prefixedPlan.unicodePairs[0].pairPair.valid == 0 || prefixedPlan.unicodePairs[0].at == 0 { + t.Fatalf("no displaced confirmation anchor: anchors=%+v confirm=%+v", prefixedPlan.unicodePairs, prefixedConfirm) + } + prefixedHaystack := strings.Repeat("z", 64) + strings.ToUpper(prefixedNeedle) + strings.Repeat("z", 4096) + if got, ok := prefixedPlan.find(prefixedHaystack); !ok || got != (Match{Pattern: 0, Start: 64}) { + t.Fatalf("displaced-anchor Find = %+v,%t want start 64", got, ok) + } + + if got := makeUnicodePairConfirm("Σя", 0); !got.valid() || got[8] != 3 { + t.Fatalf("three-way width-stable confirmation = %+v, want three forms", got) + } + threePlan := newSearchPlan([]string{"яраΣ"}) + threeConfirm := threePlan.unicodePairConfirm() + hasThreeWay := func(confirm unicodePairConfirm) bool { + for part := range int(confirm[unicodePairConfirmNAt]) { + if confirm[part*unicodePairConfirmPartSize+8] == 3 { + return true + } + } + for skipped := range confirm.skippedN() { + at := unicodePairConfirmSkippedAt + skipped*unicodePairConfirmPartSize + if confirm[at+8] == 3 { + return true + } + } + return false + } + if !threeConfirm.valid() || threeConfirm.skippedN() != unicodePairConfirmSkippedParts || !hasThreeWay(threeConfirm) { + t.Fatalf("three-way plan confirmation = %+v", threeConfirm) + } + threeHaystack := strings.Repeat("x", 64) + "ЯРАς" + strings.Repeat("x", 4096) + if got, ok := threePlan.find(threeHaystack); !ok || got != (Match{Pattern: 0, Start: 64}) { + t.Fatalf("three-way Find = %+v,%t want start 64", got, ok) + } + unsupported := []struct { + pattern, rendering string + }{ + {"kя", "KЯ"}, // Kelvin sign changes the first token width. + {"ϴя", "θЯ"}, // Greek theta has four width-stable simple-fold spellings. + {"\x80я", "\x80Я"}, // Malformed bytes retain opaque matching. + {strings.Repeat("я", unicodePairConfirmMaxParts+1), strings.Repeat("Я", unicodePairConfirmMaxParts+1)}, + } + for _, tc := range unsupported { + if got := makeUnicodePairConfirm(tc.pattern, 0); got.valid() { + t.Fatalf("unsupported confirmation shape %q compiled as %+v", tc.pattern, got) + } + fallback := newSearchPlan([]string{tc.pattern}) + if confirm := fallback.unicodePairConfirm(); confirm.valid() { + t.Fatalf("unsupported plan %q retained raw confirmation %+v", tc.pattern, confirm) + } + haystack := strings.Repeat("x", 64) + tc.rendering + strings.Repeat("x", 4096) + want := reference(haystack, tc.pattern) + if got, ok := fallback.find(haystack); !ok || got != (Match{Pattern: 0, Start: want}) { + t.Fatalf("fallback Find(%q) = %+v,%t want start %d", tc.pattern, got, ok, want) + } + } + + // The vector transition is an optimization only. Disabling its final ISA + // feature must keep the decoded pair-pair executor's answer unchanged. + if cpu.X86.HasAVX512F && cpu.X86.HasAVX512BW && cpu.X86.HasAVX512VBMI { + hasVBMI := cpu.X86.HasAVX512VBMI + cpu.X86.HasAVX512VBMI = false + defer func() { cpu.X86.HasAVX512VBMI = hasVBMI }() + check(t, strings.Repeat("x", 64)+strings.ToUpper(needle)+strings.Repeat("x", 4096)) + check(t, strings.Repeat("x", 64)+nearMiss+strings.Repeat("x", 4096)) } } diff --git a/scripts/measure_benchmarkbar.py b/scripts/measure_benchmarkbar.py new file mode 100644 index 0000000..e16e7fc --- /dev/null +++ b/scripts/measure_benchmarkbar.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +"""Adapt a complete one-sample BenchmarkBar run to claim metrics. + +The acceptance marker is deliberately derived by the repository verifier rather +than by an aggregate ratio calculation. A baseline may legitimately lose rows, +so the adapter first validates the complete field and dispatch contract without +the win predicate, then emits zero when the strict verifier finds any losing +row. A claim requiring this marker to rise from zero to one therefore requires +every row to satisfy x_vs_best < 1. +""" + +import argparse +import json +from pathlib import Path + +import verify_benchmarkbar as verify + + +def summarize(path: Path) -> dict[str, float]: + # This pass still requires the exact row inventory, one sample per row, + # entrant counts, and every dispatch invariant on both comparison arms. + verify.verify(path, expected_samples=1, require_wins=False) + try: + # Keep the strict repository verifier as the authority for the binding + # every-row win rule. The expected baseline is allowed to produce zero; + # the declared binary marker makes a losing candidate fail the claim. + verify.verify(path, expected_samples=1) + except verify.VerificationError: + all_rows_winning = 0.0 + else: + all_rows_winning = 1.0 + + rows = verify.parse(path) + samples = [sample for row in rows.values() for sample in row] + ratios = [sample["x_vs_best"] for sample in samples] + return { + "benchmarkbar_all_rows_winning": all_rows_winning, + "benchmarkbar_worst_x_vs_best": max(ratios), + "benchmarkbar_rows_below_one": float(sum(ratio < 1 for ratio in ratios)), + "benchmarkbar_min_entrants": min(sample["entrants"] for sample in samples), + "benchmarkbar_candidate_vector_bits": min( + sample["candidate_vector_bits"] for sample in samples + ), + "benchmarkbar_vectorscan_vector_bits": min( + sample["vectorscan_vector_bits"] for sample in samples + ), + "benchmarkbar_vectorscan_vbmi": min( + sample["vectorscan_vbmi"] for sample in samples + ), + } + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("report", type=Path) + args = parser.parse_args() + + for metric, value in summarize(args.report).items(): + print(json.dumps({"metric": metric, "value": value})) + + +if __name__ == "__main__": + main() diff --git a/scripts/measure_benchmarkbar_test.py b/scripts/measure_benchmarkbar_test.py new file mode 100644 index 0000000..c3b4f10 --- /dev/null +++ b/scripts/measure_benchmarkbar_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 + +from pathlib import Path +import tempfile +import unittest + +from measure_benchmarkbar import summarize +from verify_benchmarkbar_test import row +import verify_benchmarkbar as verify + + +def transcript(ratio=0.5, **override): + return "".join( + row(name, ratio=ratio, **override) + for name in sorted(verify.REQUIRED_ROWS) + ) + + +class MeasureBenchmarkBarTest(unittest.TestCase): + def summarize_text(self, text): + with tempfile.TemporaryDirectory() as directory: + path = Path(directory) / "bar.txt" + path.write_text(text) + return summarize(path) + + def test_strict_verifier_marks_a_complete_winning_board(self): + metrics = self.summarize_text(transcript()) + self.assertEqual(metrics["benchmarkbar_all_rows_winning"], 1) + self.assertEqual(metrics["benchmarkbar_rows_below_one"], len(verify.REQUIRED_ROWS)) + + def test_strict_verifier_marks_any_losing_row(self): + metrics = self.summarize_text(transcript(ratio=2.0)) + self.assertEqual(metrics["benchmarkbar_all_rows_winning"], 0) + self.assertEqual(metrics["benchmarkbar_rows_below_one"], 0) + + def test_non_win_contract_failure_remains_an_error(self): + with self.assertRaisesRegex(verify.VerificationError, "vectorscan_vector_bits"): + self.summarize_text(transcript(vectorscan_bits=256)) + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/measure_raw_byte.py b/scripts/measure_raw_byte.py new file mode 100644 index 0000000..041f1ac --- /dev/null +++ b/scripts/measure_raw_byte.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Adapt the shipped raw-byte Go benchmarks to the measurement contract.""" + +import argparse +import json +import re +from pathlib import Path + + +SPECS = { + "steady_state": ( + "BenchmarkRawByteDensity", + ( + "two_4KiB_one_in_32", + "two_4KiB_zero_admission", + "five_one_in_64", + "five_one_in_4", + ), + ), + "construction": ( + "BenchmarkRawByteConstruction", + ( + "two_patterns_512B", + "two_patterns_4KiB", + "five_patterns_512B", + "five_patterns_513B_zero_admission", + "five_patterns_5MiB_raw_install_and_first_use", + "two_shared_100_units_1KiB_zero_admission", + "two_mixed_folded_ascii_root_1KiB", + ), + ), + "fresh_find": ( + "BenchmarkRawByteFreshFind", + ( + "five_long_false_one_in_256", + "five_long_near_miss_one_in_256", + "five_long_sparse_one_in_8192", + "five_long_clustered", + "five_long_early_match_one_in_256", + "five_long_late_match_one_in_256", + ), + ), + "reused_find": ( + "BenchmarkRawByteFindAfterFreshFind", + ( + "five_long_reused_near_miss_one_in_256", + "five_long_reused_late_match_one_in_256", + ), + ), +} + +BENCHMARK = re.compile( + r"^(?PBenchmark\S+?)(?:-\d+)?\s+\d+\s+" + r"(?P[0-9.]+)\s+ns/op(?:\s+[0-9.]+\s+MB/s)?\s+" + r"(?P[0-9.]+)\s+B/op\s+(?P[0-9.]+)\s+allocs/op\s*$" +) + + +def parse(path: Path, mode: str) -> dict[str, dict[str, float]]: + prefix, labels = SPECS[mode] + expected = {f"{prefix}/{label}" for label in labels} + result: dict[str, dict[str, float]] = {} + for line in path.read_text().splitlines(): + match = BENCHMARK.match(line) + if match is None or match["name"] not in expected: + continue + name = match["name"] + if name in result: + raise ValueError(f"duplicate benchmark result for {name}") + result[name] = { + "ns_per_op": float(match["ns"]), + "B_per_op": float(match["bytes"]), + "allocs_per_op": float(match["allocs"]), + } + missing = expected.difference(result) + if missing: + raise ValueError(f"missing benchmark results: {', '.join(sorted(missing))}") + return result + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("mode", choices=sorted(SPECS)) + parser.add_argument("report", type=Path) + args = parser.parse_args() + + for name, values in parse(args.report, args.mode).items(): + label = name.removeprefix(SPECS[args.mode][0] + "/").replace("/", "_") + for suffix, value in values.items(): + print(json.dumps({"metric": f"{label}_{suffix}", "value": value})) + + +if __name__ == "__main__": + main() diff --git a/scripts/measure_raw_byte_test.py b/scripts/measure_raw_byte_test.py new file mode 100644 index 0000000..00edc70 --- /dev/null +++ b/scripts/measure_raw_byte_test.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 + +import tempfile +import unittest +from pathlib import Path + +from measure_raw_byte import parse + + +class MeasureRawByteTest(unittest.TestCase): + def report(self, lines: list[str]) -> Path: + directory = tempfile.TemporaryDirectory() + self.addCleanup(directory.cleanup) + path = Path(directory.name) / "bench.txt" + path.write_text("\n".join(lines) + "\n") + return path + + def test_steady_state(self) -> None: + labels = ( + "two_4KiB_one_in_32", + "two_4KiB_zero_admission", + "five_one_in_64", + "five_one_in_4", + ) + report = self.report( + [ + f"BenchmarkRawByteDensity/{label}-1 100 12.5 ns/op 327.68 MB/s 0 B/op 0 allocs/op" + for label in labels + ] + ) + got = parse(report, "steady_state") + self.assertEqual(len(got), len(labels)) + self.assertEqual(got["BenchmarkRawByteDensity/five_one_in_4"]["ns_per_op"], 12.5) + + def test_construction(self) -> None: + labels = ( + "two_patterns_512B", + "two_patterns_4KiB", + "five_patterns_512B", + "five_patterns_513B_zero_admission", + "five_patterns_5MiB_raw_install_and_first_use", + "two_shared_100_units_1KiB_zero_admission", + "two_mixed_folded_ascii_root_1KiB", + ) + report = self.report( + [ + f"BenchmarkRawByteConstruction/{label}-1 100 12.5 ns/op 0 B/op 0 allocs/op" + for label in labels + ] + ) + got = parse(report, "construction") + self.assertEqual(len(got), len(labels)) + self.assertEqual(got["BenchmarkRawByteConstruction/two_mixed_folded_ascii_root_1KiB"]["ns_per_op"], 12.5) + + def test_fresh_find(self) -> None: + labels = ( + "five_long_false_one_in_256", + "five_long_near_miss_one_in_256", + "five_long_sparse_one_in_8192", + "five_long_clustered", + "five_long_early_match_one_in_256", + "five_long_late_match_one_in_256", + ) + report = self.report( + [ + f"BenchmarkRawByteFreshFind/{label}-1 100 12.5 ns/op 0 B/op 0 allocs/op" + for label in labels + ] + ) + got = parse(report, "fresh_find") + self.assertEqual(len(got), len(labels)) + self.assertEqual( + got["BenchmarkRawByteFreshFind/five_long_near_miss_one_in_256"]["ns_per_op"], + 12.5, + ) + + def test_reused_find(self) -> None: + labels = ( + "five_long_reused_near_miss_one_in_256", + "five_long_reused_late_match_one_in_256", + ) + report = self.report( + [ + f"BenchmarkRawByteFindAfterFreshFind/{label}-1 100 12.5 ns/op 0 B/op 0 allocs/op" + for label in labels + ] + ) + got = parse(report, "reused_find") + self.assertEqual(len(got), len(labels)) + self.assertEqual( + got["BenchmarkRawByteFindAfterFreshFind/five_long_reused_late_match_one_in_256"]["ns_per_op"], + 12.5, + ) + + def test_rejects_missing_result(self) -> None: + report = self.report(["BenchmarkRawByteConstruction/two_patterns_512B-1 100 12 ns/op 0 B/op 0 allocs/op"]) + with self.assertRaisesRegex(ValueError, "missing benchmark results"): + parse(report, "construction") + + +if __name__ == "__main__": + unittest.main() diff --git a/scripts/reproduce.sh b/scripts/reproduce.sh index a06b315..4d61967 100755 --- a/scripts/reproduce.sh +++ b/scripts/reproduce.sh @@ -2,6 +2,8 @@ # Reproduce casei's benchmark: build the entire competitor field from source, # then run the scoreboard. CI builds and correctness-checks the same pinned # field on every push; the performance board requires the host contract below. +# Set CASEI_NATIVE_DIR to retain the native field outside the default temporary +# directory. CASEI_PREPARE_ONLY=1 stops after that unprivileged field build. # # Requirements: Go 1.24+ on x86-64 Linux with AVX2 and AVX-512F/BW/VBMI # (Intel Ice Lake or newer). @@ -42,24 +44,59 @@ if [ "${#missing[@]}" -ne 0 ]; then exit 1 fi -echo "==> Installing build dependencies (cargo, cmake, boost, pkg-config)" -sudo apt-get update -qq -sudo apt-get install -y -qq cargo cmake curl libboost-dev pkg-config python3-pip build-essential +if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then + echo "==> Installing build dependencies (cargo, cmake, boost, pkg-config)" + sudo apt-get update -qq + sudo apt-get install -y -qq cargo cmake curl libboost-dev pkg-config python3-pip build-essential +else + # The arena builders are unprivileged. Permit a prepared container to use its + # existing toolchain when sudo is unavailable or cannot run noninteractively. + missing_tools=() + for tool in cargo cc c++ cmake curl dpkg-deb make pkg-config python3 sha256sum tar; do + if ! command -v "$tool" >/dev/null 2>&1; then + missing_tools+=("$tool") + fi + done + if [ "${#missing_tools[@]}" -ne 0 ] || [ ! -r /usr/include/boost/version.hpp ]; then + echo "Build dependencies are missing and sudo is unavailable." >&2 + if [ "${#missing_tools[@]}" -ne 0 ]; then + echo "Missing tools: ${missing_tools[*]}." >&2 + fi + if [ ! -r /usr/include/boost/version.hpp ]; then + echo "Missing Boost headers (install libboost-dev)." >&2 + fi + exit 1 + fi + echo "==> Using preinstalled build dependencies (sudo is unavailable)" +fi root="$(cd "$(dirname "$0")/.." && pwd)" -native="$(mktemp -d)" +native="${CASEI_NATIVE_DIR:-$(mktemp -d)}" +mkdir -p "$native" export GOPATH="${GOPATH:-$native/go}" export GOCACHE="${GOCACHE:-$native/go-build}" +# rure's Cargo registry and target tree are part of this field build. Keep them +# in the caller-owned native directory instead of a shared host CARGO_HOME. +export CARGO_HOME="$native/cargo-home" cd "$root/arena" for dep in pcre2 vectorscan rure rustac stringzilla; do echo "==> Building competitor from source: $dep" "./$dep/prepare.sh" "$native" done +if [ "${CASEI_PREPARE_ONLY:-}" = 1 ]; then + echo "==> Native field prepared in $native" + exit 0 +fi + export PKG_CONFIG_PATH="$native/root/usr/lib/x86_64-linux-gnu/pkgconfig" export PKG_CONFIG_SYSROOT_DIR="$native/root" export LD_LIBRARY_PATH="$native/root/usr/lib/x86_64-linux-gnu" +echo "==> Checking arena adapters" +go vet ./... +go test ./... + echo "==> Running the scoreboard (BenchmarkBar: x_vs_best per row, with per-entrant dispatched width)" bar_output="$native/benchmarkbar.txt" go test -run '^$' -bench '^BenchmarkBar$' -benchtime 30x -count 3 | tee "$bar_output" diff --git a/scripts/verify_benchmarkbar.py b/scripts/verify_benchmarkbar.py index 9968cde..5986f71 100755 --- a/scripts/verify_benchmarkbar.py +++ b/scripts/verify_benchmarkbar.py @@ -11,6 +11,9 @@ PREFIX = "BenchmarkBar/" +# EXPECTED_ROWS is the board published before focused Unicode rows were added. +# REQUIRED_ROWS is the current acceptance board: every member is subject to the +# same win, entrant-count, and dispatch requirements. EXPECTED_ROWS = frozenset( { "multi/multi_N2_miss_log_1mb", @@ -48,8 +51,23 @@ "single/torture_miss_64kb", } ) +TARGETED_ROWS = frozenset( + { + "multi/multi_N1_unicode_pair_miss_1_5mb", + } +) +RAW_TRANSITION_ROWS = frozenset( + { + "multi/multi_N5_raw_transition_miss_5mb", + "multi/multi_N5_raw_transition_late_hit_5mb", + } +) +REQUIRED_ROWS = EXPECTED_ROWS | TARGETED_ROWS | RAW_TRANSITION_ROWS UTF8_ROWS = frozenset( { + "multi/multi_N1_unicode_pair_miss_1_5mb", + "multi/multi_N5_raw_transition_miss_5mb", + "multi/multi_N5_raw_transition_late_hit_5mb", "multi/multi_N512_miss_hazard_64kb", "multi/multi_N64_miss_ru_64kb", "multi/multi_N8_hazard_hit_1mb", @@ -137,14 +155,14 @@ def parse(path): return rows -def verify(path, expected_samples=3): +def verify(path, expected_samples=3, require_wins=True): rows = parse(path) found = set(rows) - if found != EXPECTED_ROWS: + if found != REQUIRED_ROWS: raise VerificationError( f"{path}: row inventory differs; " - f"missing={sorted(EXPECTED_ROWS - found)}, " - f"unexpected={sorted(found - EXPECTED_ROWS)}" + f"missing={sorted(REQUIRED_ROWS - found)}, " + f"unexpected={sorted(found - REQUIRED_ROWS)}" ) wrong_counts = { @@ -159,7 +177,11 @@ def verify(path, expected_samples=3): for sample_number, sample in enumerate(samples, 1): label = f"{name} sample {sample_number}" ratio = sample["x_vs_best"] - if not 0 < ratio < 1: + if ratio <= 0: + raise VerificationError( + f"{path}: {label} has non-positive x_vs_best={ratio:g}" + ) + if require_wins and ratio >= 1: raise VerificationError( f"{path}: {label} loses with x_vs_best={ratio:g}" ) @@ -249,8 +271,8 @@ def verify(path, expected_samples=3): worst_row = max(medians, key=medians.get) worst_sample = max( sample["x_vs_best"] - for samples in rows.values() - for sample in samples + for name in REQUIRED_ROWS + for sample in rows[name] ) median_speedup = median(1 / ratio for ratio in medians.values()) entrant_counts = [ @@ -259,7 +281,8 @@ def verify(path, expected_samples=3): for sample in samples ] return ( - f"PASS: 33/33 rows; worst median {worst_row}={medians[worst_row]:.4f}; " + f"PASS: {len(REQUIRED_ROWS)}/{len(REQUIRED_ROWS)} rows; " + f"worst median {worst_row}={medians[worst_row]:.4f}; " f"worst sample={worst_sample:.4f}; median speedup={median_speedup:.2f}x; " f"entrants={min(entrant_counts)}-{max(entrant_counts)}; " "casei=512-bit; Vectorscan=512-bit VBMI; field dispatch verified" diff --git a/scripts/verify_benchmarkbar_test.py b/scripts/verify_benchmarkbar_test.py index b5262cc..606ef1b 100755 --- a/scripts/verify_benchmarkbar_test.py +++ b/scripts/verify_benchmarkbar_test.py @@ -56,7 +56,7 @@ def row( def transcript(**override): lines = [] - for index, name in enumerate(sorted(verify.EXPECTED_ROWS)): + for index, name in enumerate(sorted(verify.REQUIRED_ROWS)): values = override if index == 0 else {} for _ in range(3): lines.append(row(name, **values)) @@ -72,7 +72,7 @@ def verify_text(self, text): def test_accepts_complete_winning_full_width_board(self): summary = self.verify_text(transcript()) - self.assertIn("PASS: 33/33 rows", summary) + self.assertIn("PASS: 36/36 rows", summary) self.assertIn("casei=512-bit", summary) def test_rejects_losing_sample(self): @@ -98,16 +98,36 @@ def test_rejects_unmeasured_row(self): def test_rejects_missing_row(self): text = "".join( row(name) - for name in sorted(verify.EXPECTED_ROWS)[:-1] + for name in sorted(verify.REQUIRED_ROWS)[:-1] for _ in range(3) ) with self.assertRaisesRegex(verify.VerificationError, "row inventory differs"): self.verify_text(text) + def test_rejects_missing_unicode_confirmation_row(self): + row_name = "multi/multi_N1_unicode_pair_miss_1_5mb" + text = "".join( + line + for line in transcript().splitlines(keepends=True) + if f"/{row_name.split('/', 1)[1]}-" not in line + ) + with self.assertRaisesRegex(verify.VerificationError, "row inventory differs"): + self.verify_text(text) + + def test_rejects_missing_raw_transition_row(self): + row_name = "multi/multi_N5_raw_transition_late_hit_5mb" + text = "".join( + line + for line in transcript().splitlines(keepends=True) + if f"/{row_name.split('/', 1)[1]}-" not in line + ) + with self.assertRaisesRegex(verify.VerificationError, "row inventory differs"): + self.verify_text(text) + def test_rejects_wrong_sample_count(self): with self.assertRaisesRegex(verify.VerificationError, "wrong sample counts"): self.verify_text( - transcript() + row(sorted(verify.EXPECTED_ROWS)[0]) + transcript() + row(sorted(verify.REQUIRED_ROWS)[0]) ) diff --git a/scripts/verify_throughput.py b/scripts/verify_throughput.py index af4ccb5..aed0835 100755 --- a/scripts/verify_throughput.py +++ b/scripts/verify_throughput.py @@ -13,7 +13,7 @@ sys.dont_write_bytecode = True SCRIPT_DIR = Path(__file__).resolve().parent sys.path.insert(0, str(SCRIPT_DIR)) -from verify_benchmarkbar import EXPECTED_ROWS, is_utf8_row # noqa: E402 +from verify_benchmarkbar import REQUIRED_ROWS, is_utf8_row # noqa: E402 VISIBLE = ( @@ -99,11 +99,11 @@ def parse(path): def verify(path, expected_samples=3, require_wins=True): rows = parse(path) found = set(rows) - if found != EXPECTED_ROWS: + if found != REQUIRED_ROWS: raise VerificationError( f"{path}: row inventory differs; " - f"missing={sorted(EXPECTED_ROWS - found)}, " - f"unexpected={sorted(found - EXPECTED_ROWS)}" + f"missing={sorted(REQUIRED_ROWS - found)}, " + f"unexpected={sorted(found - REQUIRED_ROWS)}" ) medians = {} @@ -134,7 +134,7 @@ def verify(path, expected_samples=3, require_wins=True): def render(medians, title, selected=None): - rows = set(medians) if selected is None else set(selected) + rows = REQUIRED_ROWS if selected is None else set(selected) unknown = rows - set(medians) if unknown: raise VerificationError(f"unknown selected rows: {sorted(unknown)}") @@ -164,11 +164,12 @@ def render(medians, title, selected=None): def summary(medians): - ratios = {row: result[2] for row, result in medians.items()} + ratios = {row: medians[row][2] for row in REQUIRED_ROWS} narrowest = min(ratios, key=ratios.get) widest = max(ratios, key=ratios.get) return ( - f"PASS: 33/33 throughput rows; narrowest {narrowest}={ratios[narrowest]:.2f}x; " + f"PASS: {len(REQUIRED_ROWS)}/{len(REQUIRED_ROWS)} throughput rows; " + f"narrowest {narrowest}={ratios[narrowest]:.2f}x; " f"widest {widest}={ratios[widest]:.2f}x; three samples per lane" ) diff --git a/scripts/verify_throughput_test.py b/scripts/verify_throughput_test.py index 0c44d4a..87fa203 100755 --- a/scripts/verify_throughput_test.py +++ b/scripts/verify_throughput_test.py @@ -25,7 +25,7 @@ def benchmark(row, engine, speed=1000, serial=False): def transcript(omit=None, samples=3, losing=None, serial=False): lines = [] - for row in sorted(verify.EXPECTED_ROWS): + for row in sorted(verify.REQUIRED_ROWS): for engine in sorted(engines(row)): if (row, engine) == omit: continue @@ -44,17 +44,22 @@ def verify_text(self, text): def test_accepts_complete_winning_board_and_renders_markdown(self): medians = self.verify_text(transcript()) - self.assertEqual(33, len(medians)) + self.assertEqual(len(verify.REQUIRED_ROWS), len(medians)) + self.assertIn( + f"PASS: {len(verify.REQUIRED_ROWS)}/{len(verify.REQUIRED_ROWS)} throughput rows", + verify.summary(medians), + ) table = verify.render(medians, "Test CPU") self.assertIn("#### Test CPU", table) + self.assertIn("multi_N1_unicode_pair_miss_1_5mb", table) self.assertIn("**2.0**", table) self.assertIn("**2.00×**", table) def test_accepts_gce_serial_tab_encoding(self): - self.assertEqual(33, len(self.verify_text(transcript(serial=True)))) + self.assertEqual(len(verify.REQUIRED_ROWS), len(self.verify_text(transcript(serial=True)))) def test_rejects_missing_row(self): - first = sorted(verify.EXPECTED_ROWS)[0] + first = sorted(verify.REQUIRED_ROWS)[0] text = "".join( line for line in transcript().splitlines(keepends=True) @@ -63,6 +68,16 @@ def test_rejects_missing_row(self): with self.assertRaisesRegex(verify.VerificationError, "row inventory differs"): self.verify_text(text) + def test_rejects_missing_unicode_confirmation_row(self): + row = "multi/multi_N1_unicode_pair_miss_1_5mb" + text = "".join( + line + for line in transcript().splitlines(keepends=True) + if f"/{row.split('/', 1)[1]}/" not in line + ) + with self.assertRaisesRegex(verify.VerificationError, "row inventory differs"): + self.verify_text(text) + def test_rejects_missing_required_engine(self): row = "single/log_miss_1mb" with self.assertRaisesRegex(verify.VerificationError, "missing engines"): diff --git a/unicode_confirm.go b/unicode_confirm.go new file mode 100644 index 0000000..bd0f01f --- /dev/null +++ b/unicode_confirm.go @@ -0,0 +1,266 @@ +package casei + +import "unicode/utf8" + +const ( + unicodePairConfirmMaxParts = 20 + unicodePairConfirmPartSize = 10 + unicodePairConfirmSkippedParts = 2 + + unicodePairConfirmSkippedAt = (unicodePairConfirmMaxParts - unicodePairConfirmSkippedParts) * unicodePairConfirmPartSize + unicodePairConfirmMaxLengthAt = unicodePairConfirmMaxParts * unicodePairConfirmPartSize + unicodePairConfirmAnchorAt = unicodePairConfirmMaxLengthAt + 1 + unicodePairConfirmNAt = unicodePairConfirmMaxLengthAt + 2 + unicodePairConfirmValidAt = unicodePairConfirmMaxLengthAt + 3 + unicodePairConfirmPackedSize = unicodePairConfirmMaxLengthAt + 4 + unicodePairConfirmMinAt = unicodePairConfirmPackedSize + unicodePairConfirmVariableSize = unicodePairConfirmPackedSize + 1 + unicodePairConfirmVariableFlag = 2 +) + +// unicodePairConfirm is stable assembly input for one bounded literal. The +// 204-byte fixed layout stores up to three one- or two-byte values plus their +// source offset in each ten-byte part. A 205-byte variable layout instead +// stores up to three three-byte-padded raw forms per part and adds the minimum +// possible match width; its cursor advances by the form that actually matched. +// Both layouts finish with maximum width, anchor offset, part count, and flags. +type unicodePairConfirm string + +func (confirm unicodePairConfirm) valid() bool { + if (len(confirm) != unicodePairConfirmPackedSize && len(confirm) != unicodePairConfirmVariableSize) || + confirm[unicodePairConfirmValidAt]&1 == 0 || + confirm[unicodePairConfirmMaxLengthAt] == 0 || confirm[unicodePairConfirmAnchorAt] >= confirm[unicodePairConfirmMaxLengthAt] { + return false + } + if confirm.variable() { + parts := int(confirm[unicodePairConfirmNAt]) + return len(confirm) == unicodePairConfirmVariableSize && parts > 0 && parts <= unicodePairConfirmMaxParts && + confirm[unicodePairConfirmMinAt] > 0 && confirm[unicodePairConfirmMinAt] <= confirm[unicodePairConfirmMaxLengthAt] + } + if len(confirm) != unicodePairConfirmPackedSize { + return false + } + skipped := confirm.skippedN() + parts := int(confirm[unicodePairConfirmNAt]) + return (skipped == 0 || skipped == unicodePairConfirmSkippedParts) && parts+skipped <= unicodePairConfirmMaxParts && + (parts != 0 || skipped != 0) +} + +func (confirm unicodePairConfirm) variable() bool { + return len(confirm) > unicodePairConfirmValidAt && confirm[unicodePairConfirmValidAt]&unicodePairConfirmVariableFlag != 0 +} + +func (confirm unicodePairConfirm) maxLength() int { + return int(confirm[unicodePairConfirmMaxLengthAt]) +} + +func (confirm unicodePairConfirm) minLength() int { + if confirm.variable() && len(confirm) == unicodePairConfirmVariableSize { + return int(confirm[unicodePairConfirmMinAt]) + } + return confirm.maxLength() +} + +func (confirm unicodePairConfirm) anchorAt() int { + return int(confirm[unicodePairConfirmAnchorAt]) +} + +func (confirm unicodePairConfirm) skippedN() int { + return int(confirm[unicodePairConfirmValidAt] >> 1) +} + +// makeUnicodePairConfirm moves pair-pair's two raw tokens to trailing slots +// when confirmAt is supplied. The vector transition proves those slots from +// its low-six-bit tables plus UTF-8 byte classes; matchWidthAt still checks +// every slot and remains a complete raw-token oracle for scalar replay. +func makeUnicodePairConfirm(pattern string, anchorAt int, confirmAt ...int) unicodePairConfirm { + if anchorAt < 0 || anchorAt > 255 || len(pattern) > 255 || len(confirmAt) > 1 { + return "" + } + + skippedAt := [unicodePairConfirmSkippedParts]int{} + skipN := 0 + if len(confirmAt) != 0 { + if confirmAt[0] < 0 || confirmAt[0] > 255 || confirmAt[0] == anchorAt { + return "" + } + skippedAt[0], skippedAt[1] = anchorAt, confirmAt[0] + skipN = unicodePairConfirmSkippedParts + } + + forms, _ := patternRawForms(pattern) + packed := make([]byte, unicodePairConfirmPackedSize) + at, parts, skipped := 0, 0, 0 + for _, unit := range forms { + r, size := utf8.DecodeRuneInString(pattern[at:]) + if r == utf8.RuneError && size == 1 || len(unit) == 0 || len(unit) > 3 { + return "" + } + width := len(unit[0]) + if width < 1 || width > 2 || width != size { + return "" + } + + var packedPart [unicodePairConfirmPartSize]byte + packedPart[6], packedPart[7], packedPart[8] = uint8(at), uint8(width), uint8(len(unit)) + for i, form := range unit { + if len(form) != width { + return "" + } + value := uint16(form[0]) + if width == 2 { + value |= uint16(form[1]) << 8 + } + valueAt := i * 2 + packedPart[valueAt], packedPart[valueAt+1] = uint8(value), uint8(value>>8) + } + + isSkipped := false + for i := range skipN { + if at == skippedAt[i] { + isSkipped = true + break + } + } + if isSkipped { + if skipped == skipN { + return "" + } + partAt := unicodePairConfirmSkippedAt + skipped*unicodePairConfirmPartSize + copy(packed[partAt:], packedPart[:]) + skipped++ + } else { + if parts == unicodePairConfirmMaxParts-skipN { + return "" + } + partAt := parts * unicodePairConfirmPartSize + copy(packed[partAt:], packedPart[:]) + parts++ + } + at += size + } + if at != len(pattern) || parts+skipped == 0 || skipped != skipN { + return "" + } + packed[unicodePairConfirmMaxLengthAt] = uint8(at) + packed[unicodePairConfirmAnchorAt] = uint8(anchorAt) + packed[unicodePairConfirmNAt] = uint8(parts) + packed[unicodePairConfirmValidAt] = 1 | uint8(skipped<<1) + return unicodePairConfirm(string(packed)) +} + +// makeUnicodePairVariableConfirm records the same literal as a short sequence +// of raw forms. Unlike the fixed-offset representation above, its confirmation +// cursor advances by the width of the form that actually matched. The pair-pair +// screen still fixes the start: makeUnicodePairAnchor only records anchors +// before the first width-changing fold orbit. +func makeUnicodePairVariableConfirm(pattern string, anchorAt int) unicodePairConfirm { + if anchorAt < 0 || anchorAt > 255 || !utf8.ValidString(pattern) { + return "" + } + forms, _ := patternRawForms(pattern) + if len(forms) == 0 || len(forms) > unicodePairConfirmMaxParts { + return "" + } + packed := make([]byte, unicodePairConfirmVariableSize) + minLength, maxLength := 0, 0 + for part, unit := range forms { + if len(unit) == 0 || len(unit) > 3 { + return "" + } + minWidth, maxWidth := utf8.UTFMax+1, 0 + partAt := part * unicodePairConfirmPartSize + for formIndex, form := range unit { + if len(form) == 0 || len(form) > 3 { + return "" + } + copy(packed[partAt+formIndex*3:], form) + if len(form) < minWidth { + minWidth = len(form) + } + if len(form) > maxWidth { + maxWidth = len(form) + } + } + packed[partAt+9] = byte(len(unit)) + minLength += minWidth + maxLength += maxWidth + } + if minLength == maxLength || maxLength > 255 { + return "" + } + packed[unicodePairConfirmMaxLengthAt] = byte(maxLength) + packed[unicodePairConfirmAnchorAt] = byte(anchorAt) + packed[unicodePairConfirmNAt] = byte(len(forms)) + packed[unicodePairConfirmValidAt] = 1 | unicodePairConfirmVariableFlag + packed[unicodePairConfirmMinAt] = byte(minLength) + return unicodePairConfirm(string(packed)) +} + +func (confirm unicodePairConfirm) matchesPartAt(haystack string, at, partAt int) bool { + value := uint16(haystack[at+int(confirm[partAt+6])]) + if confirm[partAt+7] == 2 { + value |= uint16(haystack[at+int(confirm[partAt+6])+1]) << 8 + } + if value == uint16(confirm[partAt])|uint16(confirm[partAt+1])<<8 { + return true + } + if confirm[partAt+8] >= 2 && value == uint16(confirm[partAt+2])|uint16(confirm[partAt+3])<<8 { + return true + } + return confirm[partAt+8] >= 3 && value == uint16(confirm[partAt+4])|uint16(confirm[partAt+5])<<8 +} + +func (confirm unicodePairConfirm) matchWidthAt(haystack string, at int) (int, bool) { + if !confirm.valid() || at < 0 || len(haystack)-at < confirm.minLength() { + return 0, false + } + start := at + if confirm.variable() { + for part := 0; part < int(confirm[unicodePairConfirmNAt]); part++ { + partAt := part * unicodePairConfirmPartSize + matched := false + for form := 0; form < int(confirm[partAt+9]); form++ { + formAt := partAt + form*3 + width := 1 + switch first := confirm[formAt]; { + case first >= 0xe0: + width = 3 + case first >= 0xc0: + width = 2 + } + if len(haystack)-at < width { + continue + } + equal := true + for i := 0; i < width; i++ { + equal = equal && haystack[at+i] == confirm[formAt+i] + } + if equal { + at += width + matched = true + break + } + } + if !matched { + return 0, false + } + } + return at - start, true + } + if len(haystack)-at < confirm.maxLength() { + return 0, false + } + for part := range int(confirm[unicodePairConfirmNAt]) { + if !confirm.matchesPartAt(haystack, at, part*unicodePairConfirmPartSize) { + return 0, false + } + } + for skipped := range confirm.skippedN() { + partAt := unicodePairConfirmSkippedAt + skipped*unicodePairConfirmPartSize + if !confirm.matchesPartAt(haystack, at, partAt) { + return 0, false + } + } + return confirm.maxLength(), true +} diff --git a/unicode_variable_confirm_test.go b/unicode_variable_confirm_test.go new file mode 100644 index 0000000..89b6d5a --- /dev/null +++ b/unicode_variable_confirm_test.go @@ -0,0 +1,122 @@ +package casei + +import ( + "strings" + "testing" +) + +func variableConfirmRenderings(forms [][]string, at int, prefix string, out *[]string) { + if at == len(forms) { + *out = append(*out, prefix) + return + } + for _, form := range forms[at] { + variableConfirmRenderings(forms, at+1, prefix+form, out) + } +} + +func TestUnicodePairVariableConfirm(t *testing.T) { + const needle = "Шерлок Холмс" + plan := newSearchPlan([]string{needle}) + confirm := plan.unicodePairConfirm() + if plan.unicodePairs[0].pairPair.valid == 0 || !confirm.valid() || !confirm.variable() { + t.Fatalf("variable confirmation was not compiled: pair=%+v confirm=%x", plan.unicodePairs[0].pairPair, string(confirm)) + } + if confirm.minLength() >= confirm.maxLength() { + t.Fatalf("confirmation bounds = [%d,%d], want a width-changing range", confirm.minLength(), confirm.maxLength()) + } + + forms, _ := patternRawForms(needle) + var renderings []string + variableConfirmRenderings(forms, 0, "", &renderings) + for _, rendering := range renderings { + width, ok := confirm.matchWidthAt(rendering, 0) + if !ok || width != len(rendering) || !plan.matchesSingleAt(rendering, 0) { + t.Fatalf("confirmation rejected rendering %x", rendering) + } + } + nearMiss := strings.TrimSuffix(needle, "с") + "я" + if _, ok := confirm.matchWidthAt(nearMiss, 0); ok { + t.Fatalf("confirmation accepted near miss %x", nearMiss) + } + + matcher := NewMatcher([]string{needle}) + anchor := &plan.unicodePairs[0] + for _, offset := range []int{0, 1, 63, 64, 127, 128, 4095} { + for _, rendering := range renderings { + haystack := strings.Repeat("x", offset) + rendering + strings.Repeat("x", 256) + got, width, ok := plan.findWithWidth(haystack) + wantWidth := 0 + if plan.chooseUnicodePairAnchor(haystack) != nil && unicodePairConfirmVectorEnabled() { + wantWidth = len(rendering) + } + if !ok || got != (Match{Pattern: 0, Start: offset}) || width != wantWidth { + t.Fatalf("offset %d rendering %x: findWithWidth=%+v,%d,%t", offset, rendering, got, width, ok) + } + // findUnicodePairConfirm is the VBMI route selected by + // findUnicodePairAnchor. Do not call it directly on hosts that + // cannot execute its full-block kernel. + if unicodePairConfirmVectorEnabled() { + got, width, ok = plan.findUnicodePairConfirm(haystack, anchor) + if !ok || got != (Match{Pattern: 0, Start: offset}) || width != len(rendering) { + t.Fatalf("offset %d rendering %x: direct confirmation=%+v,%d,%t", offset, rendering, got, width, ok) + } + } + calls := 0 + if completed := matcher.Each(haystack, func(match Match, width int) bool { + calls++ + if match != (Match{Pattern: 0, Start: offset}) || width != len(rendering) { + t.Errorf("offset %d rendering %x: Each yielded %+v,%d", offset, rendering, match, width) + } + return true + }); !completed || calls != 1 { + t.Fatalf("offset %d rendering %x: Each completed=%t calls=%d", offset, rendering, completed, calls) + } + } + } + // A conservative pair-pair survivor is not a match. Confirmation must + // continue within the same vector block and return the later exact one. + late := nearMiss + "x" + renderings[len(renderings)-1] + wantStart := len(nearMiss) + 1 + if got, width, ok := plan.findUnicodePairConfirm(late, anchor); !ok || got != (Match{Pattern: 0, Start: wantStart}) || width != len(renderings[len(renderings)-1]) { + t.Fatalf("false candidate then match: direct confirmation=%+v,%d,%t", got, width, ok) + } + + // A shorter rendering can begin after the final max-width-safe vector + // start; the scalar tail must still inspect it. + shortest := renderings[0] + for _, rendering := range renderings[1:] { + if len(rendering) < len(shortest) { + shortest = rendering + } + } + haystack := strings.Repeat("x", 4096) + shortest + wantWidth := 0 + if unicodePairConfirmVectorEnabled() { + wantWidth = len(shortest) + } + if got, width, ok := plan.findWithWidth(haystack); !ok || got != (Match{Pattern: 0, Start: 4096}) || width != wantWidth { + t.Fatalf("short tail findWithWidth=%+v,%d,%t", got, width, ok) + } + if got, width, ok := plan.findUnicodePairConfirm(shortest, anchor); !ok || got != (Match{Pattern: 0}) || width != len(shortest) { + t.Fatalf("bare short rendering: direct confirmation=%+v,%d,%t", got, width, ok) + } + if got, ok := matcher.Find(shortest); !ok || got != (Match{Pattern: 0}) { + t.Fatalf("bare short rendering: Find=%+v,%t", got, ok) + } +} + +func TestUnicodePairVariableConfirmRejectsMalformedPattern(t *testing.T) { + const needle = "Шер\x80лок Холмс" + plan := newSearchPlan([]string{needle}) + if plan.unicodePairs[0].pairPair.valid == 0 { + t.Fatal("fixture did not compile a pair-pair screen") + } + if confirm := plan.unicodePairConfirm(); confirm.valid() { + t.Fatalf("malformed pattern compiled a variable confirmation: %x", string(confirm)) + } + haystack := strings.Repeat("x", 97) + strings.ToUpper("Шер") + "\x80" + strings.ToUpper("лок Холмс") + if got, ok := plan.find(haystack); !ok || got != (Match{Pattern: 0, Start: 97}) { + t.Fatalf("fallback Find=%+v,%t", got, ok) + } +}