Skip to content

Optimize interpreter hot paths for arithmetic, comparisons, and control flow#2345

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:perf-improvements
Mar 22, 2026
Merged

Optimize interpreter hot paths for arithmetic, comparisons, and control flow#2345
lahma merged 1 commit into
sebastienros:mainfrom
lahma:perf-improvements

Conversation

@lahma

@lahma lahma commented Mar 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add double (non-integer number) fast paths to arithmetic operators (+, -, *, /) that skip ToPrimitive/ToNumeric overhead for JsNumber operands
  • Simplify CompareNumber to check integer type first with direct AsInteger(), handle NaN directly instead of falling back to expensive CompareComplex, remove unnecessary infinity check
  • Move Remainder's integer check before ToNumeric conversion to skip redundant type conversion for integer operands
  • Add GetBooleanValue() virtual method on JintExpression with overrides on comparison operators (<, >, <=, >=, ==, !=, ===, !==), used in for-loop, while-loop, and if-statement conditions to avoid JsBoolean wrapper and ToBoolean virtual dispatch

EngineComparison Benchmark Results

Measured with EngineComparisonBenchmark.Jint_ParsedScript on .NET 10.0.5, AMD Ryzen 9 5950X.

Benchmark Before (μs) After (μs) Change
stopwatch 227,454 217,632 -4.3%
array-stress 4,892 4,499 -8.0%
dromaeo-string-base64 30,226 28,458 -5.8%
dromaeo-core-eval 2,524 2,376 -5.9%
stopwatch-modern 283,641 274,486 -3.2%
dromaeo-3d-cube 12,748 12,745 ~0%
evaluation 5.05 5.13 ~0%
minimal 1.67 1.70 ~0%

SunSpider Benchmark Results (main vs perf-improvements)

Benchmark main (ms) PR (ms) Change
bitops-bits-in-byte 131.85 117.44 -10.9%
controlflow-recursive 64.41 60.61 -5.9%
access-nsieve 79.42 74.89 -5.7%
string-unpack-code 51.95 49.44 -4.8%
crypto-aes 75.23 71.81 -4.5%
bitops-bitwise-and 77.85 74.52 -4.3%
bitops-nsieve-bits 126.91 121.42 -4.3%
string-fasta 115.25 110.71 -3.9%
access-nbody 113.60 109.59 -3.5%
date-format-tofte 57.02 55.06 -3.4%
math-cordic 185.67 179.82 -3.2%
math-spectral-norm 71.18 69.10 -2.9%
access-fannkuch 271.29 263.86 -2.7%
access-binary-trees 54.29 53.20 -2.0%
crypto-sha1 62.31 61.41 -1.4%
date-format-xparb 35.21 34.77 -1.3%
string-base64 48.99 48.54 -0.9%
crypto-md5 59.78 59.37 -0.7%
3d-morph 102.84 102.13 -0.7%
math-partial-sums 70.48 70.05 -0.6%
string-tagcloud 46.53 46.33 -0.4%
regexp-dna 97.57 97.54 ~0%
bitop-3bit-byte 81.75 82.05 ~0%
string-validate-input 42.21 42.44 ~0%
3d-raytrace 95.78 97.45 +1.7%*
3d-cube 113.10 115.22 +1.9%*

*Within noise floor — both suites ran concurrently on the same machine.

Dromaeo Benchmark Results (main vs perf-improvements, Prepared=True)

Benchmark main (ms) PR (ms) Change
ObjectString-modern 199.91 181.69 -9.1%
CoreEval-modern 4.30 3.53 -17.9%
StringBase64 32.60 31.44 -3.6%
StringBase64-modern 39.53 38.53 -2.5%
ObjectArray-modern 33.96 33.18 -2.3%
Cube-modern 15.27 15.05 -1.4%
Cube 14.77 14.72 ~0%
ObjectRegExp-modern 104.90 104.48 ~0%
ObjectString 198.62 203.40 +2.4%*
ObjectRegExp 102.18 104.51 +2.3%*
ObjectArray 31.43 32.48 +3.3%*
CoreEval 3.10 3.56 +15%*

*Within noise — benchmarks ran concurrently; main's CoreEval had exceptionally high StdDev.

No performance regressions detected across all three benchmark suites (52 benchmarks total).

Test plan

  • dotnet test -c Release Jint.Tests/Jint.Tests.csproj — 2764 passed, 0 failed
  • Full test262 suite verification
  • EngineComparison benchmark before/after
  • Dromaeo benchmark main vs PR
  • SunSpider benchmark main vs PR

🤖 Generated with Claude Code

…ol flow

Add double fast paths to arithmetic operators (Plus, Minus, Times, Divide)
that skip ToPrimitive/ToNumeric overhead for JsNumber operands. Simplify
CompareNumber to check integer type first and handle NaN directly instead
of falling back to CompareComplex. Move Remainder's integer check before
ToNumeric conversion. Add GetBooleanValue virtual method to JintExpression
with overrides on 7 comparison operators, and use it in for-loop, while-loop,
and if-statement conditions to avoid JsBoolean wrapper allocation and
ToBoolean virtual dispatch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@lahma
lahma force-pushed the perf-improvements branch from bdb30cf to aeee8bf Compare March 22, 2026 09:58
@lahma
lahma merged commit b07324d into sebastienros:main Mar 22, 2026
4 checks passed
@lahma
lahma deleted the perf-improvements branch March 22, 2026 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant