Recorded on July 22, 2026 with:
Runtime: Node.js 26.4.0, x64
Operating system: Windows 10.0.26200
Processor: Intel Core i7-14700K, 28 logical CPUs
Measured clock: approximately 5.3 GHz
Harness: Mitata 1.0.34
Run the suite with pnpm benchmark. See README.md for workload and comparison
boundaries.
The before values were captured immediately before the execution-plan work on the same machine. The after values use the final grouped suite. Means can vary slightly between runs.
| Workload | Before | After | Improvement |
|---|---|---|---|
| Exact mutation, two nested paths | 8.82 us | 332.80 ns | 26.5x |
| Immutable clone, two matched paths | 10.51 us | 679.80 ns | 15.5x |
| Clone, one array wildcard | 16.26 us | 1.60 us | 10.2x |
| Mutate, one array wildcard | 15.07 us | 832.67 ns | 18.1x |
| Email detection, 1 KB | 12.21 us | 11.81 us | 1.03x |
These values come from the final focused exact-path run after the full suite. Each mutation case includes only the reset for fields it changed. Allocation is Mitata's average heap allocation per iteration.
| Workload | Safe mean | Codegen mean | Safe allocation | Codegen allocation | Speedup |
|---|---|---|---|---|---|
| One shallow path | 109.52 ns | 106.16 ns | 96.70 B | 96.47 B | 1.03x |
| Two nested paths | 277.85 ns | 236.72 ns | 384.22 B | 384.55 B | 1.17x |
| Five paths | 716.03 ns | 510.61 ns | 770.10 B | 672.23 B | 1.40x |
| Ten paths | 1.46 us | 1.05 us | 1.69 KB | 1.41 KB | 1.39x |
| Two missing paths | 39.83 ns | 16.77 ns | 0.40 B | 0.16 B | 2.37x |
| Two shared-parent paths | 289.07 ns | 216.91 ns | 384.21 B | 288.15 B | 1.33x |
| Two array-index paths | 407.16 ns | 342.58 ns | 576.59 B | 479.88 B | 1.19x |
fast-redact, two paths |
39.41 ns | - | 120.19 B | - | - |
fast-redact, ten paths |
172.98 ns | - | 288.14 B | - | - |
| Direct assignments, two | 3.12 ns | - | 0.11 B | - | - |
The generated two-path plan meets the documented acceptable target of less than 250 ns while
retaining descriptor checks, getter safety, array semantics, and built-in-container exclusions. The
one-path case meets the less than 200 ns target. fast-redact is faster for its narrower mutation
contract and remains included as context, not as a semantics-equivalent implementation.
| Compiler | Mean time | Average allocation |
|---|---|---|
| Redactive safe, two exact paths | 4.79 us | 4.43 KB |
| Redactive codegen, two paths | 8.20 us | 2.08 KB |
fast-redact, two paths |
4.67 us | 4.10 KB |
@pinojs/redact, two paths |
573.82 ns | 2.13 KB |
Generated compilation adds approximately 3.41 us to redactor creation. Dividing that premium by the measured 41.13 ns two-path call saving gives an approximate break-even of 83 calls. The one-path difference is close to benchmark noise, so codegen should not be selected for a one-path policy based on throughput alone. Break-even changes with path sharing, object shape, Node.js JIT state, and hardware.
fast-redact defaults to mutating the input, serializing it with JSON.stringify, and restoring
the input internally. Group F measures that default contract separately from Group A's advanced
serialize: false mutation comparison.
| Workload | Two paths | Ten paths |
|---|---|---|
JSON.stringify without redaction |
283.97 ns | - |
| Redactive clone, then stringify | 1.14 us | 2.44 us |
| Redactive safe mutate, stringify, fixture reset | 632.98 ns | 1.87 us |
| Redactive codegen mutate, stringify, fixture reset | 585.76 ns | 1.47 us |
fast-redact default serialize and restore |
339.66 ns | 496.84 ns |
For two paths, default fast-redact is approximately 1.72x faster than Redactive codegen plus
serialization and 1.86x faster than safe mutation plus serialization. For ten paths, those gaps
are approximately 2.96x and 3.76x. The Redactive mutation rows use known fixture values for reset;
the clone rows are the general source-preserving Redactive contract. The raw Group A gap is larger
because serialization does not dominate that measurement.
| Group | Benchmark | Mean time |
|---|---|---|
| B | Redactive, two matched selective paths | 726.27 ns |
| B | Redactive, two missing selective paths | 362.54 ns |
| B | @pinojs/redact, two matched paths | 924.46 ns |
| C | Redactive clone, one array wildcard | 1.50 us |
| C | Redactive mutate, one array wildcard | 783.38 ns |
| C | Redactive clone, recursive wildcard | 16.00 us |
| D | Redactive email detection, 1 KB | 11.40 us |
| D | Redactive email detection, 10 KB | 122.62 us |
| D | Redactive email detection, 100 KB | 1.34 ms |
| D | Redactive email detection, 1,000 KB | 12.30 ms |
| E | Redactive wildcard plus detector compile | 2.24 us |
| F | Redactive codegen serialize, two paths | 585.76 ns |
| F | fast-redact default, two paths |
339.66 ns |
Safe exact mutation, generated mutation, and selective clone meet their stated primary targets on this fixture. Missing exact mutation is effectively allocation-free. Matched mutation retains descriptor allocations for getter safety and property-flag compatibility.
Recursive wildcards and multi-rule generic traversal remain the largest structured optimization opportunity. Text detection remains linear and is dominated by detector expression cost at larger sizes.