Skip to content

RegExp syntax checking performance - #58339

Merged
Ron Buckton (rbuckton) merged 8 commits into
mainfrom
regexp-syntax-perf
Apr 29, 2024
Merged

RegExp syntax checking performance#58339
Ron Buckton (rbuckton) merged 8 commits into
mainfrom
regexp-syntax-perf

Conversation

@rbuckton

@rbucktonRon Buckton (rbuckton) commented Apr 27, 2024

Copy link
Copy Markdown
Contributor

This makes a few changes to the RegExp syntax checking algorithm for possible performance improvements. This also fixes a small typo in one of the RegExp diagnostic messages.

One of the changes is to ensure we perform proper bounds checks when pos might advance past end. To accomplish this, I added the charCodeChecked and charCodeUnchecked functions. charCodeChecked performs boundary tests which both improves reliability and avoids potential deoptimizations due to reading past the end of a string. charCodeUnchecked is simply a wrapper for text.charCodeAt and exists primarily to make it easier to readily identify unchecked vs checked reads from text. charCodeUnchecked should only be used when we've already performed a bounds check before reading a character, such as in a while (pos < end) loop. I've also done the same for code points with codePointChecked and codePointUnchecked. Each of these functions is small, so ideally will be inlined by an optimizing compiler like the one used by V8.

I've primarily focused on optimizing scanRegularExpressionWorker for now. If this seems effective, I will investigate adopting charCodeChecked in more places in the scanner in a later PR.

I've also made a few other small perf improvements:

  • We now delay allocations for capture group tracking until they are necessary.
  • scanRegularExpressionWorker has been moved out of reScanSlashToken and updated to use the existing text and end values from the outer scope.
  • A few frequently referenced variables from the RegExp scanner have been switched to var to avoid TDZ check overhead.

@rbuckton

Copy link
Copy Markdown
ContributorAuthor

TypeScript Bot (@typescript-bot) perf test

@typescript-bot

TypeScript Bot (typescript-bot) commented Apr 27, 2024

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
perf test✅ Started❌ Results

@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton), the perf run you requested failed. You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-Unions - node (v18.15.0, x64)
Errors3030~~~p=1.000 n=6
Symbols62,15462,154~~~p=1.000 n=6
Types50,27350,273~~~p=1.000 n=6
Memory used192,825k (± 0.74%)192,796k (± 0.75%)~192,135k195,762kp=0.521 n=6
Parse Time2.02s (± 1.38%)1.95s (± 0.46%)🟩-0.07s (- 3.62%)1.94s1.96sp=0.005 n=6
Bind Time1.07s (± 1.09%)1.07s (± 0.96%)~1.06s1.08sp=0.437 n=6
Check Time14.04s (± 0.08%)14.08s (± 0.29%)+0.04s (+ 0.30%)14.04s14.13sp=0.040 n=6
Emit Time3.87s (± 0.90%)3.88s (± 0.44%)~3.86s3.90sp=0.627 n=6
Total Time21.00s (± 0.09%)20.98s (± 0.23%)~20.91s21.04sp=0.686 n=6
angular-1 - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols945,172945,172~~~p=1.000 n=6
Types408,068408,068~~~p=1.000 n=6
Memory used1,222,036k (± 0.00%)1,222,022k (± 0.00%)~1,221,973k1,222,117kp=0.378 n=6
Parse Time6.92s (± 0.50%)6.78s (± 0.50%)-0.15s (- 2.14%)6.75s6.84sp=0.005 n=6
Bind Time1.87s (± 0.71%)1.87s (± 0.28%)~1.87s1.88sp=0.672 n=6
Check Time31.41s (± 0.32%)31.36s (± 0.17%)~31.27s31.42sp=0.295 n=6
Emit Time14.57s (± 0.82%)14.65s (± 0.75%)~14.56s14.86sp=0.809 n=6
Total Time54.77s (± 0.42%)54.66s (± 0.33%)~54.52s55.00sp=0.297 n=6
mui-docs - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols1,954,6351,954,635~~~p=1.000 n=6
Types676,418676,418~~~p=1.000 n=6
Memory used1,753,442k (± 0.00%)1,753,451k (± 0.00%)~1,753,422k1,753,484kp=0.630 n=6
Parse Time6.89s (± 0.31%)6.73s (± 0.35%)-0.17s (- 2.42%)6.70s6.76sp=0.005 n=6
Bind Time2.31s (± 0.18%)2.31s (± 0.33%)~2.30s2.32sp=1.000 n=6
Check Time56.81s (± 0.11%)56.85s (± 0.45%)~56.63s57.29sp=0.470 n=6
Emit Time0.14s (± 2.88%)0.14s~~~p=0.405 n=6
Total Time66.16s (± 0.13%)66.03s (± 0.38%)~65.82s66.43sp=0.297 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,215,5671,215,606+39 (+ 0.00%)~~p=0.001 n=6
Types257,612257,638+26 (+ 0.01%)~~p=0.001 n=6
Memory used2,323,147k (± 0.03%)2,323,519k (± 0.02%)~2,323,071k2,324,130kp=0.471 n=6
Parse Time7.56s (± 0.61%)7.44s (± 1.06%)-0.12s (- 1.59%)7.34s7.57sp=0.016 n=6
Bind Time2.75s (± 0.48%)2.75s (± 0.85%)~2.73s2.78sp=0.936 n=6
Check Time49.78s (± 0.59%)49.66s (± 0.78%)~49.29s50.38sp=0.471 n=6
Emit Time3.91s (± 1.63%)3.95s (± 3.43%)~3.85s4.22sp=0.810 n=6
Total Time64.01s (± 0.48%)63.82s (± 0.61%)~63.55s64.57sp=0.173 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,215,5671,215,606+39 (+ 0.00%)~~p=0.001 n=6
Types257,612257,638+26 (+ 0.01%)~~p=0.001 n=6
Memory used2,396,896k (± 0.01%)2,397,995k (± 0.02%)+1,099k (+ 0.05%)2,397,126k2,398,511kp=0.008 n=6
Parse Time5.25s (± 1.17%)5.15s (± 0.75%)-0.09s (- 1.78%)5.10s5.20sp=0.016 n=6
Bind Time1.70s (± 1.33%)1.69s (± 1.71%)~1.64s1.73sp=0.870 n=6
Check Time34.43s (± 0.21%)34.41s (± 0.17%)~34.34s34.47sp=0.471 n=6
Emit Time2.63s (± 0.83%)2.65s (± 1.54%)~2.60s2.70sp=0.575 n=6
Total Time44.02s (± 0.23%)43.91s (± 0.22%)~43.81s44.04sp=0.199 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols256,196256,224+28 (+ 0.01%)~~p=0.001 n=6
Types103,640103,656+16 (+ 0.02%)~~p=0.001 n=6
Memory used424,190k (± 0.01%)424,200k (± 0.01%)~424,167k424,242kp=0.471 n=6
Parse Time3.49s (± 1.55%)3.33s (± 0.35%)🟩-0.16s (- 4.72%)3.31s3.34sp=0.005 n=6
Bind Time1.30s (± 0.90%)1.30s (± 0.84%)~1.29s1.32sp=0.865 n=6
Check Time18.21s (± 0.37%)18.18s (± 0.39%)~18.09s18.27sp=0.687 n=6
Emit Time1.36s (± 1.28%)1.38s (± 0.89%)~1.36s1.39sp=0.241 n=6
Total Time24.37s (± 0.31%)24.18s (± 0.32%)-0.18s (- 0.76%)24.06s24.25sp=0.005 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors3535~~~p=1.000 n=6
Symbols224,824224,824~~~p=1.000 n=6
Types93,39093,390~~~p=1.000 n=6
Memory used369,410k (± 0.05%)369,296k (± 0.00%)-114k (- 0.03%)369,279k369,315kp=0.037 n=6
Parse Time3.67s (± 0.38%)3.53s (± 1.05%)🟩-0.14s (- 3.91%)3.49s3.59sp=0.005 n=6
Bind Time1.95s (± 1.41%)1.94s (± 0.78%)~1.92s1.96sp=0.413 n=6
Check Time19.48s (± 0.41%)19.44s (± 0.24%)~19.36s19.49sp=0.195 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time25.10s (± 0.30%)24.90s (± 0.21%)-0.20s (- 0.80%)24.83s24.97sp=0.005 n=6
vscode - node (v18.15.0, x64)
Errors44~~~p=1.000 n=6
Symbols2,797,1492,797,149~~~p=1.000 n=6
Types950,053950,053~~~p=1.000 n=6
Memory used2,925,215k (± 0.00%)2,925,305k (± 0.00%)~2,925,155k2,925,515kp=0.575 n=6
Parse Time13.56s (± 0.28%)13.32s (± 0.30%)-0.24s (- 1.79%)13.26s13.38sp=0.005 n=6
Bind Time4.12s (± 2.10%)4.09s (± 0.25%)~4.07s4.10sp=0.615 n=6
Check Time73.08s (± 0.39%)73.11s (± 0.48%)~72.52s73.49sp=0.689 n=6
Emit Time21.41s (± 9.45%)21.03s (± 8.39%)~19.61s23.52sp=0.810 n=6
Total Time112.17s (± 1.88%)111.54s (± 1.59%)~110.03s114.21sp=0.575 n=6
webpack - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols265,853265,853~~~p=1.000 n=6
Types108,438108,438~~~p=1.000 n=6
Memory used410,385k (± 0.02%)410,331k (± 0.01%)~410,276k410,388kp=0.109 n=6
Parse Time3.95s (± 0.56%)3.84s (± 0.61%)-0.11s (- 2.74%)3.80s3.87sp=0.005 n=6
Bind Time1.69s (± 0.79%)1.67s (± 0.63%)-0.02s (- 1.38%)1.65s1.68sp=0.017 n=6
Check Time17.05s (± 0.41%)17.06s (± 0.30%)~16.97s17.10sp=0.936 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time22.69s (± 0.36%)22.57s (± 0.33%)-0.12s (- 0.54%)22.43s22.64sp=0.045 n=6
xstate-main - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols523,981523,981~~~p=1.000 n=6
Types178,708178,708~~~p=1.000 n=6
Memory used461,203k (± 0.01%)461,166k (± 0.01%)~461,120k461,206kp=0.298 n=6
Parse Time2.69s (± 0.61%)2.61s (± 0.56%)-0.08s (- 2.92%)2.59s2.63sp=0.005 n=6
Bind Time0.98s (± 0.64%)0.99s (± 0.82%)+0.01s (+ 1.36%)0.98s1.00sp=0.023 n=6
Check Time15.47s (± 0.36%)15.31s (± 0.26%)-0.16s (- 1.02%)15.26s15.36sp=0.005 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time19.14s (± 0.24%)18.91s (± 0.19%)-0.23s (- 1.18%)18.87s18.97sp=0.005 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Compiler-Unions - node (v18.15.0, x64)
  • angular-1 - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • ts-pre-modules - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate-main - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

tsserver

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-UnionsTSServer - node (v18.15.0, x64)
Req 1 - updateOpen3,504ms (± 0.33%)3,421ms (± 0.43%)-83ms (- 2.36%)3,399ms3,436msp=0.005 n=6
Req 2 - geterr7,555ms (± 0.59%)7,546ms (± 0.55%)~7,478ms7,603msp=0.575 n=6
Req 3 - references439ms (± 1.96%)428ms (± 1.03%)-12ms (- 2.62%)423ms436msp=0.016 n=6
Req 4 - navto336ms (± 0.36%)337ms (± 0.75%)~334ms341msp=0.803 n=6
Req 5 - completionInfo count1,3571,357~~~p=1.000 n=6
Req 5 - completionInfo112ms (± 1.04%)116ms (± 8.29%)~111ms135msp=0.867 n=6
CompilerTSServer - node (v18.15.0, x64)
Req 1 - updateOpen3,701ms (± 1.21%)3,581ms (± 0.38%)🟩-120ms (- 3.25%)3,556ms3,593msp=0.005 n=6
Req 2 - geterr5,702ms (± 0.16%)5,685ms (± 0.40%)~5,652ms5,715msp=0.128 n=6
Req 3 - references445ms (± 0.46%)443ms (± 0.46%)~441ms447msp=0.145 n=6
Req 4 - navto341ms (± 1.35%)340ms (± 1.31%)~333ms346msp=1.000 n=6
Req 5 - completionInfo count1,5191,519~~~p=1.000 n=6
Req 5 - completionInfo111ms (± 6.02%)109ms (± 0.90%)~107ms110msp=0.929 n=6
xstate-main-1-tsserver - node (v18.15.0, x64)
Req 1 - updateOpen6,228ms (± 0.67%)7,346ms (± 8.35%)~6,095ms7,632msp=0.066 n=6
Req 2 - geterr1,633ms (± 8.49%)1,627ms (± 8.59%)~1,342ms1,695msp=0.810 n=6
Req 3 - references127ms (± 3.66%)123ms (± 9.38%)~100ms133msp=0.934 n=6
Req 4 - navto588ms (± 2.73%)584ms (± 2.54%)~573ms609msp=0.871 n=6
Req 5 - completionInfo count3,4133,413~~~p=1.000 n=6
Req 5 - completionInfo1,273ms (± 1.81%)1,261ms (± 1.97%)~1,228ms1,304msp=0.423 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • CompilerTSServer - node (v18.15.0, x64)
  • Compiler-UnionsTSServer - node (v18.15.0, x64)
  • xstate-main-1-tsserver - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

startup

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
tsc-startup - node (v18.15.0, x64)
Execution time227.45ms (± 0.18%)227.31ms (± 0.17%)-0.14ms (- 0.06%)225.53ms231.35msp=0.001 n=600
tsserver-startup - node (v18.15.0, x64)
Execution time359.11ms (± 0.27%)359.09ms (± 0.28%)~350.85ms367.65msp=0.655 n=600
tsserverlibrary-startup - node (v18.15.0, x64)
Execution time287.26ms (± 0.28%)287.27ms (± 0.32%)~280.38ms306.23msp=0.291 n=600
typescript-startup - node (v18.15.0, x64)
Execution time286.91ms (± 0.30%)286.91ms (± 0.28%)~280.02ms293.59msp=0.230 n=600
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • tsc-startup - node (v18.15.0, x64)
  • tsserver-startup - node (v18.15.0, x64)
  • tsserverlibrary-startup - node (v18.15.0, x64)
  • typescript-startup - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@rbuckton

Copy link
Copy Markdown
ContributorAuthor

@typescript-bot

TypeScript Bot (typescript-bot) commented Apr 27, 2024

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
run dt✅ Started✅ Results
test top400✅ Started✅ Results
test tsserver top100✅ Started
user test this✅ Started✅ Results
user test tsserver✅ Started✅ Results

@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton) Here are the results of running the user tests comparing main and refs/pull/58339/merge:

Everything looks good!

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Ron Buckton (@rbuckton), the results of running the DT tests are ready.

Everything looks the same!

You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton) Here are the results of running the user tests comparing main and refs/pull/58339/merge:

Everything looks good!

Comment threadsrc/compiler/scanner.ts Outdated
Comment threadsrc/compiler/scanner.ts
@typescript-bot

Copy link
Copy Markdown
Contributor

Ron Buckton (@rbuckton) Here are the results of running the top 400 repos comparing main and refs/pull/58339/merge:

Everything looks good!

@jakebailey

Copy link
Copy Markdown
Member

The perf seels really good. Is that all from avoiding out of bounds?

@rbuckton

Copy link
Copy Markdown
ContributorAuthor

The perf seels really good. Is that all from avoiding out of bounds?

Yeah, if charCodeAt is called for an out of bounds index it returns NaN, which isn't an SMI. IIRC, accessing a string out of bounds also results in sub optional compilation as it requires a recompile to introduce additional checks in the compiled code.

Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com>
Comment threadsrc/compiler/scanner.ts
@DanielRosenwasser

Copy link
Copy Markdown
Member

Might be worth mentioning in the PR description that you also var-ified the regular expression parser (#52924).

@DanielRosenwasser

Copy link
Copy Markdown
Member

Also other specific optimizations - like hoisting out helper functions and lazily initializing state for captures.

@jakebaileyJake Bailey (jakebailey) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, forgot my green check.

@rbuckton

Copy link
Copy Markdown
ContributorAuthor

I've been working on expanding this throughout scanner.ts and writing up a lint rule to ensure enforcement, so I'll probably need another review shortly.

@rbuckton

Copy link
Copy Markdown
ContributorAuthor

I've been working on expanding this throughout scanner.ts and writing up a lint rule to ensure enforcement, so I'll probably need another review shortly.

Since I have some additional testing to do, I think I'll put those changes up as a separate PR following this one.

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@rbuckton@typescript-bot@jakebailey@DanielRosenwasser