Skip to content

Commit 8bf7b6c

Browse files
committed
perf: add fast validation plan
1 parent 2b02932 commit 8bf7b6c

26 files changed

Lines changed: 4374 additions & 525 deletions

changelogs/unreleased.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Unreleased
22

3+
## 2026-07-07
4+
5+
- **FastPlan correctness**: Fixed root raw JSON Schema cache invalidation for caller-owned nested constraint mutations and made root simple custom-validator fast paths honor the active global Locale default messages.
6+
- **FastPlan Phase 3 verification**: Re-ran local Node.js v20.20.2 / Windows x64 benchmarks after the primitive/enum optimization review. The library baseline is S1 simple valid `~1.672M ops/s`, S2 invalid without i18n formatting `~169K ops/s`, and S3 nested valid `~1.443M ops/s`; repeated Zod scenario runs were `15/19`, `16/19`, and `16/19`, with U1 union string and E1 enum as the stable remaining Zod-leading scenarios and several near-1x scenarios treated as benchmark noise, not public performance claims.
7+
- **Docs consistency**: Synced the FAQ and design philosophy benchmark tables with the maintained 2026-07-07 performance-guide baseline.
8+
9+
## 2026-07-06
10+
11+
- **Performance tooling**: Declared `tinybench@2.9.0` as a direct devDependency, captured the Batch 0 before baseline, added JSON-capable benchmark reports, added `bench:smoke` / `bench:full` / `bench:cache`, and added root / pure / runtime / Validator entry-matrix coverage.
12+
- **Validation hot path**: Added instance-local schema runtime metadata caching, shared smart-coercion candidate reuse, lazy error-format context creation, runtime normalization caching, and fast-path skips for schemas without Conditional, async custom validators, or AJV-skipped-property traversal needs.
13+
- **Validator correctness**: Extended the `__proto__` skipped-property compensation path across schema applicators used by the metadata fast path, with regression coverage for `allOf`.
14+
- **Performance baseline**: Updated the maintained local benchmark baseline on Node.js v20.20.2 / Windows x64: S1 simple valid `~1.574M ops/s`, S2 invalid without i18n formatting `~321K ops/s`, and S3 nested valid `~1.427M ops/s`.
15+
- **Zod scenario matrix**: Added `bench:zod`, included the extended Zod comparison matrix in `bench:smoke` / `bench:full`, and recorded git dirty state in scenario JSON metadata for reproducible performance attribution.
16+
- **FastPlan groundwork**: Added the private `ValidationPlan` skeleton and schema runtime metadata slots with Phase 1 fallback semantics, so future fast-path subsets can be introduced behind explicit feature gates without changing public APIs.
17+
- **FastPlan execution layer**: Expanded the private `ValidationPlan` valid-path subset to scalar / enum / primitive union / homogeneous array / object / email format schemas, added root and `DslBuilder` plan caches, optimized single-field smart coercion, and added guarded sync/async custom-validator fast paths while preserving AJV / Conditional / custom fallback behavior for unsupported or invalid cases.
18+
- **FastPlan benchmark result**: On the initial local Node.js v20.20.2 / Windows x64 Zod full matrix, schema-dsl won 15/19 scenarios; remaining Zod-leading scenarios were recorded as follow-up optimization tail items rather than public performance claims.
19+
320
## 2026-07-02
421

522
- **Brand visual**: Refined the documentation logo SVG to a cleaner routed `s` trace with a reduced-motion-safe trace animation in the SVG asset.

docs/en/design-philosophy.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ Performance is important, but it is not mixed into the design philosophy page as
148148

149149
| Scenario | schema-dsl throughput |
150150
|------|-----------|
151-
| S1 simple valid object | ~1.185M ops/s |
152-
| S2 invalid object without i18n formatting | ~1.178M ops/s |
153-
| S3 nested valid object | ~941K ops/s |
151+
| S1 simple valid object | ~1.672M ops/s |
152+
| S2 invalid object without i18n formatting | ~169K ops/s |
153+
| S3 nested valid object | ~1.443M ops/s |
154154

155-
Environment: Node.js v20.20.2, Windows x64, run time 2026-06-18T08:49:22.365Z.
155+
Environment: Node.js v20.20.2, Windows x64, run time 2026-07-07T03:20:24.821Z.
156156

157157
For tuning guidance, see [Performance Optimization Guide](performance-guide.md).
158158

docs/en/faq.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,11 @@ console.log(result.data);
225225

226226
| Scenario | schema-dsl throughput |
227227
|------|-----------|
228-
| S1 simple valid object | ~1.185M ops/s |
229-
| S2 invalid object without i18n formatting | ~1.178M ops/s |
230-
| S3 nested valid object | ~941K ops/s |
228+
| S1 simple valid object | ~1.672M ops/s |
229+
| S2 invalid object without i18n formatting | ~169K ops/s |
230+
| S3 nested valid object | ~1.443M ops/s |
231231

232-
**Environment**: Node.js v20.20.2, Windows x64, run time 2026-06-18T08:49:22.365Z.
232+
**Environment**: Node.js v20.20.2, Windows x64, run time 2026-07-07T03:20:24.821Z.
233233

234234
**Conclusion**:
235235
- ✅ Hot-path validation is already in the million-ops/sec range on this local machine.

docs/en/performance-guide.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ Latest local run:
1414

1515
| Scenario | schema-dsl throughput |
1616
|------|-----------|
17-
| S1 simple valid object | ~1.320M ops/s |
18-
| S2 invalid object without i18n formatting | ~1.235M ops/s |
19-
| S3 nested valid object | ~1.007M ops/s |
17+
| S1 simple valid object | ~1.672M ops/s |
18+
| S2 invalid object without i18n formatting | ~169K ops/s |
19+
| S3 nested valid object | ~1.443M ops/s |
2020

21-
Environment: Node.js v20.20.2, Windows x64, run time 2026-06-22T14:19:51.306Z.
21+
Environment: Node.js v20.20.2, Windows x64, run time 2026-07-07T03:20:24.821Z.
2222

2323
Use these numbers as a regression baseline for this project. Re-run the benchmark when Node.js, dependencies, schema complexity, or error formatting behavior changes.
2424

@@ -92,7 +92,9 @@ For truly one-off, high-cardinality dynamic schemas, isolate that path and keep
9292

9393
```powershell
9494
npm test
95-
npm run bench
95+
npm run bench:smoke
96+
npm run bench:full
97+
npm run bench:cache
9698
```
9799

98100
---

docs/zh/design-philosophy.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ parser 和 compiler 都是运行时组件,因此同一份 schema 定义可以
148148

149149
| 场景 | schema-dsl 吞吐 |
150150
|------|-----------|
151-
| S1 简单有效对象 | ~1.185M ops/s |
152-
| S2 无效对象,不做 i18n 格式化 | ~1.178M ops/s |
153-
| S3 嵌套有效对象 | ~941K ops/s |
151+
| S1 简单有效对象 | ~1.672M ops/s |
152+
| S2 无效对象,不做 i18n 格式化 | ~169K ops/s |
153+
| S3 嵌套有效对象 | ~1.443M ops/s |
154154

155-
环境:Node.js v20.20.2,Windows x64,运行时间 2026-06-18T08:49:22.365Z
155+
环境:Node.js v20.20.2,Windows x64,运行时间 2026-07-07T03:20:24.821Z
156156

157157
调优建议见 [性能优化指南](performance-guide.md)
158158

docs/zh/faq.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,16 +225,16 @@ console.log(result.data);
225225

226226
| 场景 | schema-dsl 吞吐 |
227227
|------|-----------|
228-
| S1 简单有效对象 | ~1.185M ops/s |
229-
| S2 无效对象,不做 i18n 格式化 | ~1.178M ops/s |
230-
| S3 嵌套有效对象 | ~941K ops/s |
228+
| S1 简单有效对象 | ~1.672M ops/s |
229+
| S2 无效对象,不做 i18n 格式化 | ~169K ops/s |
230+
| S3 嵌套有效对象 | ~1.443M ops/s |
231231

232232
**结论**:
233233
- ✅ 在这台本地机器上,热路径验证已处于百万 ops/sec 级别。
234234
- ✅ 内置缓存可避免复用 schema 时重复解析。
235235
- ✅ 这些数字适合作为回归基线;运行时、依赖或 schema 复杂度变化后应重新跑 benchmark。
236236

237-
**环境**: Node.js v20.20.2,Windows x64,运行时间 2026-06-18T08:49:22.365Z
237+
**环境**: Node.js v20.20.2,Windows x64,运行时间 2026-07-07T03:20:24.821Z
238238

239239
---
240240

docs/zh/performance-guide.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
| 场景 | schema-dsl 吞吐 |
1616
|------|-----------|
17-
| S1 简单有效对象 | ~1.320M ops/s |
18-
| S2 无效对象,不做 i18n 格式化 | ~1.235M ops/s |
19-
| S3 嵌套有效对象 | ~1.007M ops/s |
17+
| S1 简单有效对象 | ~1.672M ops/s |
18+
| S2 无效对象,不做 i18n 格式化 | ~169K ops/s |
19+
| S3 嵌套有效对象 | ~1.443M ops/s |
2020

21-
环境:Node.js v20.20.2,Windows x64,运行时间 2026-06-22T14:19:51.306Z
21+
环境:Node.js v20.20.2,Windows x64,运行时间 2026-07-07T03:20:24.821Z
2222

2323
这些数字适合作为当前项目的回归基线。Node.js、依赖、schema 复杂度或错误格式化行为变化后,应重新运行 benchmark。
2424

@@ -92,7 +92,9 @@ app.post('/users', (req, res) => {
9292

9393
```powershell
9494
npm test
95-
npm run bench
95+
npm run bench:smoke
96+
npm run bench:full
97+
npm run bench:cache
9698
```
9799

98100
---

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@
134134
"test:version": "node -e \"const p=require('./package.json');const {VERSION}=require('./dist/index.cjs');if(p.version!==VERSION)throw new Error('Version mismatch: '+p.version+' vs '+VERSION);console.log('Version OK:',p.version)\"",
135135
"test:all:with-audit": "npm run lint && npm run build && npm run test:interop && npm run typecheck && npm run test:types && npm test && npm run test:version && npm run test:audit",
136136
"bench": "node test/benchmarks/library-comparison.js",
137+
"bench:zod": "node test/benchmarks/zod-scenario-matrix.js --json",
138+
"bench:smoke": "node test/benchmarks/library-comparison.js --smoke --json && node test/benchmarks/entry-matrix.js --smoke --json && node test/benchmarks/zod-scenario-matrix.js --smoke --json",
139+
"bench:full": "node test/benchmarks/library-comparison.js --json && node test/benchmarks/entry-matrix.js --json && node test/benchmarks/zod-scenario-matrix.js --json",
140+
"bench:cache": "node test/benchmarks/cache-stability.js --json",
137141
"prepublishOnly": "npm run test:all:with-audit && npm pack --dry-run"
138142
},
139143
"keywords": [
@@ -220,6 +224,7 @@
220224
"eslint": "9.39.4",
221225
"fastest-validator": "1.19.1",
222226
"joi": "18.1.2",
227+
"tinybench": "2.9.0",
223228
"tsup": "8.5.1",
224229
"typescript": "5.9.3",
225230
"vitest": "3.2.6",

0 commit comments

Comments
 (0)