perf(codegen): skip escaping harmless < tokens - #25564
Merged
Merged
Conversation
camc314
force-pushed
the
codex/codegen-string-escape-fast-path
branch
from
August 12, 2026 17:50
49e7a9d to
949f180
Compare
camc314
marked this pull request as ready for review
August 12, 2026 17:51
Contributor
Author
|
@codex review |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Contributor
Author
Merge activity
|
## Summary - Detect actual case-insensitive `</script` sequences in the initial string-escape scan. - Keep strings containing only harmless `<` on the bulk-write fast path. - Add regression coverage for script closers, controls, paired and lone surrogates, and template quasis. ## Benchmark methodology No permanent microbenchmark is added. Measurements used release bundles built with `pnpm --filter oxc-codegen run build` on Node v26.5.0, a one-off focused harness over representative string-literal ASTs, and the existing `packages/codegen/bench.bench.ts` parsed-AST fixtures. The focused harness used ten warmup batches and 20 measured batches per case; Vitest fixtures used 1s warmup and 3s measurement windows (50/20 iteration minima). The removed one-off harness is retained for reference at [bench.string.bench.ts](https://github.com/oxc-project/oxc/blob/49e7a9d43bdc55a8f01075363bb8701ca5a9380c/packages/codegen/bench.string.bench.ts). Focused release results (ms/print, mean ± standard deviation): | Case | Before | After | Change | | --- | ---: | ---: | ---: | | Short ordinary string | 0.00003 ± 0.00000 | 0.00003 ± 0.00000 | no material change | | Long string without `<` | 0.02048 ± 0.00114 | 0.01906 ± 0.00038 | within noise / slightly faster | | Dense harmless HTML/SVG-like `<` (15,360 chars) | 0.05625 ± 0.00152 | 0.01283 ± 0.00036 | 77% faster | | Mixed text with harmless `<` | 0.04766 ± 0.00210 | 0.02371 ± 0.00072 | 50% faster | | Frequent mixed-case `</script` closers | 0.04350 ± 0.00074 | 0.04366 ± 0.00079 | within noise | Existing parsed-AST benchmark fixtures (Vitest RME 0.15–0.79%): Radix 0.0028 -> 0.0027 ms, React development 0.0981 -> 0.0976 ms. App.tsx varied from 0.6261 to 0.6657 ms after versus 0.6415 ms before, so this PR makes no throughput claim for that fixture and shows no consistent regression. A release CPU profile of the dense harmless case reduced `printEscapedStringContents` from 1,099 of 1,459 samples, plus 124 `^</script` regex samples, to zero; the after profile spends 321 of 383 samples in the single initial scan.
graphite-app
Bot
force-pushed
the
codex/codegen-string-escape-fast-path
branch
from
August 13, 2026 08:49
949f180 to
5444cbf
Compare
This was referenced Aug 17, 2026
Boshen
added a commit
that referenced
this pull request
Aug 18, 2026
### 💥 BREAKING CHANGES - 365274e packages/codegen: [**BREAKING**] `printSync` return an object (#25720) (overlookmotel) ### 🚀 Features - 6a7eb60 packages/codegen: Alter capitalization of `sourceFilename` option (#25854) (overlookmotel) - 300763f packages/codegen: Add full source map support (#25585) (camc314) - a169e4a napi/minify: Expose property name mangling options (#24741) (Dunqing) - 2f5cdb1 minifier: Add property name mangling (#24740) (Dunqing) - 4922141 mangler: Deduplicate private accessor names (#25601) (camc314) - 1c4f519 napi: Add Relay transform plugin (#25503) (Boshen) - a4478e9 codegen: Add `oxc-codegen` package (#25488) (overlookmotel) ### 🐛 Bug Fixes - 0fbcf64 codegen: Validate sourcemap options (#25860) (camc314) - 345f981 react_compiler: Skip node_modules by default (#25859) (Boshen) - ab81f3f minifier: Drop side-effect-free additions (#25639) (Dunqing) - 241c559 napi/minify: Accept RegExp for property filters (#25827) (Dunqing) - 4cc7ea4 codegen: Reject invalid indent options (#25807) (camc314) - 53f9295 isolated-declarations: Preserve undefined for defaulted any (#25292) (camc314) - 8ab883a codegen: Preserve property key annotations (#25766) (Dunqing) - b13fd48 minifier: Model uninitialized module vars as undefined (#25497) (Dunqing) - f6000ac ecmascript: Fold `**` with `Number::exponentiate`, not IEEE `pow` (#25644) (Kotaro Chikuba) - b846abc isolated-declarations: Handle ambient expando properties (#25655) (camc314) - dec0a86 react-compiler: Standardize diagnostics (#25702) (Boshen) - fca2e0c parser: Reject initialized lexical declarations in for-in (#25700) (Boshen) - ae9be8f parser: Forbid type parameters on quoted constructors (#25696) (Boshen) - c5f188a react-compiler: Use Babel v1 validation defaults (#25676) (Boshen) - db44651 napi: Disable reuseWorker in browser bindings (#25640) (leaysgur) - ce35d47 react_compiler: Preserve JSX import source pragmas (#25592) (Boshen) - 059784d semantic: Respect shadowed `Infinity` and `NaN` in enum evaluation (#25604) (camc314) - bb5a232 minifier: Keep variable declaration initilized with class when keepNames is enabled (#25584) (sapphi-red) - f49229d minifier: Keep side effects when rotating bitwise operands (#25596) (Kotaro Chikuba) - e82495b ecmascript: Derive `ToNumber` of `!x` from `ToBoolean` (#25595) (Kotaro Chikuba) - 509931b semantic: Classify global references per identifier (#25608) (camc314) - 80484ce mangler: Correct base54 safety comment (#25606) (camc314) - c1369a7 codegen: Resolve private names in class heritage (#25588) (camc314) - c002f29 codegen: Escape sources for empty import specifiers (#25586) (camc314) - 0c68b7f estree: Emit `decorators` on `FormalParameterRest` (#25582) (camc314) - cdf1846 semantic: Allow legacy escapes in JSX attributes (#25576) (Boshen) - e75e102 minifier: Preserve block statement in labeled iteration statements (#25162) (Armano) - 771d79a mangler: Exclude non-manglable symbols from slot assignment (#25539) (sapphi-red) - 76b19f5 minifier: Avoid duplicating large folded strings (#25532) (Dunqing) - 59e8895 codegen: Validate starting indent level (#25550) (camc314) - 88b34f2 clippy: Remove unneeded `unsafe` (#25551) (camc314) - 23a7ad0 parser: Stop delimited lists at end of file (#25542) (Boshen) - 73acba9 parser: Preserve fatal errors during await reparse (#25541) (Boshen) - c3e99d1 minifier: Avoid invalid octal escapes in template folds (#25495) (Dunqing) - b4e6a9e codegen: Output newline after `export default interface` (#25487) (overlookmotel) - 5fcf683 minifier: Correct issue with try finally termination (#25185) (Armano) - 1645d93 react_compiler: Preserve source spans (#25462) (Boshen) - 8d7f9cf react_compiler: Honor eslint suppressions (#25394) (Boshen) ### ⚡ Performance - 568203e ecmascript: Use binary search for known globals (#25817) (Boshen) - c84ede3 estree_tokens: Share JS token update entry point (#25826) (Boshen) - 9a6e862 minifier: Move owned statements directly (#25835) (Dunqing) - 61b2aef minifier: Move owned AST nodes directly (#25837) (Dunqing) - 673b04b minifier: Replace expressions without take_in dummies (#25836) (Dunqing) - 63ff8ef linter: Outline diagnostic construction (#25762) (Boshen) - 621808e diagnostics: Measure graphemes lazily (#25723) (Boshen) - f62ed0e diagnostics: Optimize graphical number rendering (#25715) (Boshen) - 7152834 diagnostics: Reduce graphical formatting overhead (#25714) (Boshen) - 10fc4b7 diagnostics: Reduce graphical rendering allocations (#25711) (Boshen) - 9c8abab diagnostics: Batch graphical reports (#25710) (Boshen) - 757f3d4 mangler: Share allocated names across reused slots (#25605) (camc314) - 5444cbf codegen: Skip escaping harmless `<` tokens (#25564) (camc314) ### 📚 Documentation - 58f7ab9 packages/codegen: Reformat docs and comments (#25848) (overlookmotel) - 627466e transform-react: Document all options (#25800) (Boshen) - ce03ac1 packages/codegen: Fix JSDoc comments for `printSync` (#25722) (overlookmotel) - 386a699 packages/codegen: Correct JSDoc comment (#25716) (overlookmotel) - 31e571d mangler: Update code example (#25599) (camc314) - fd62354 codegen: Revamp package readme (#25560) (camc314) - ffa3153 codegen: Clarify raw transfer Node requirement (#25565) (camc314) - c5d4063 codegen: Clarify binary walk allocations (#25562) (camc314) - 5703d7a codegen: Correct stale printer comments (#25561) (camc314) Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
</scriptsequences in the initial string-escape scan.<on the bulk-write fast path.Benchmark methodology
No permanent microbenchmark is added. Measurements used release bundles built with
pnpm --filter oxc-codegen run buildon Node v26.5.0, a one-off focused harness over representative string-literal ASTs, and the existingpackages/codegen/bench.bench.tsparsed-AST fixtures. The focused harness used ten warmup batches and 20 measured batches per case; Vitest fixtures used 1s warmup and 3s measurement windows (50/20 iteration minima).The removed one-off harness is retained for reference at bench.string.bench.ts.
Focused release results (ms/print, mean ± standard deviation):
<<(15,360 chars)<</scriptclosersExisting parsed-AST benchmark fixtures (Vitest RME 0.15–0.79%): Radix 0.0028 -> 0.0027 ms, React development 0.0981 -> 0.0976 ms. App.tsx varied from 0.6261 to 0.6657 ms after versus 0.6415 ms before, so this PR makes no throughput claim for that fixture and shows no consistent regression.
A release CPU profile of the dense harmless case reduced
printEscapedStringContentsfrom 1,099 of 1,459 samples, plus 124^</scriptregex samples, to zero; the after profile spends 321 of 383 samples in the single initial scan.