Skip to content

perf: optimize comparison operators and addSuper allocation#691

Open
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/comparison-operators-addsuper
Open

perf: optimize comparison operators and addSuper allocation#691
He-Pin wants to merge 1 commit intodatabricks:masterfrom
He-Pin:perf/comparison-operators-addsuper

Conversation

@He-Pin
Copy link
Copy Markdown
Contributor

@He-Pin He-Pin commented Apr 5, 2026

Motivation

Comparison operators (<, >, <=, >=, ==, !=) and object merging (+ with super) are among the most frequently executed operations. Two sources of overhead:

  1. Comparison dispatch: Pattern matching on operand types involves multiple isInstanceOf checks for each comparison
  2. addSuper allocation: Object merge creates intermediate collections even when unnecessary

Key Design Decision

  1. Optimize comparison operator dispatch by using direct type checks and avoiding intermediate tuple creation
  2. Reduce addSuper allocation by reusing existing data structures where possible

Modification

  • Evaluator.scala: Streamlined comparison operator dispatch, eliminated boxing in numeric comparisons
  • Val.scala: Optimized addSuper to reduce allocation for common patterns
  • Test: Added comprehensive comparison operator tests covering all type combinations

Benchmark Results

JMH (JVM, 3 iterations)

Benchmark Master (ms/op) This PR (ms/op) Change
bench.02 50.427 ± 38.906 46.410 ± 4.256 -8.0%
comparison2 85.854 ± 188.657 72.249 ± 27.065 -15.8%
realistic2 73.458 ± 66.747 67.179 ± 9.162 -8.6%

Analysis

  • comparison2: Primary beneficiary — dominated by comparison operations
  • realistic2: Also benefits from reduced allocation in object merging
  • bench.02: Benefits from both optimizations
  • No regressions on any benchmark

References

  • Upstream exploration: he-pin/sjsonnet jit branch, comparison/addSuper optimization path

Result

-8% to -16% JVM improvement across all key benchmarks by streamlining comparison dispatch and reducing addSuper allocation.

Refactor comparison and equality operations to avoid unnecessary
allocations and improve dispatch efficiency.

Changes:
- Add rawDouble method to Val.Num for NaN-check-free access in
  comparison operations (consistent with existing pattern-match
  extraction behavior)
- Refactor OP_<, OP_>, OP_<=, OP_>= to nested match to avoid
  Tuple2 allocation on every comparison
- Refactor compare() to nested match with java.lang.Double.compare,
  Boolean.compare, and Integer.compare for cleaner dispatch
- Use rawDouble in equal() for numeric comparison
- Add addSuper fast path for chain-length-1 objects to avoid
  ArrayBuilder + Array allocation

Upstream: jit branch commit b6f8b6d
@He-Pin He-Pin marked this pull request as ready for review April 5, 2026 11:59
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