Skip to content

Conversation

@thomas-quadratic
Copy link
Contributor

PR description

This PR introduces performance improvements on Mod and associated EVM arithmetics operations by implementing division on multi-precision long limbs instead of int limbs. The following is a short summary of benchmarks that were done compared to current (big-endian int limbs) implementation and the relative gain in percentage:

Op Case Current (ns/op) New (ns/op) Gain
AddMod Worst 197.009 173.898 12%
Random 196.067 168.801 14%
Mod Worst 158.018 141.66 10%
Random 127.061 119.729 6%
MulMod Worst 372.789 270.915 27%
Random 284.657 244.451 14%
Smod Worst 179.966 150.011 17%
Random 160.842 141.151 12%

Thanks for sending a pull request! Have you done the following?

  • Checked out our contribution guidelines?
  • Considered documentation and added the doc-change-required label to this PR if updates are required.
  • Considered the changelog and included an update if required.
  • For database changes (e.g. KeyValueSegmentIdentifier) considered compatibility and performed forwards and backwards compatibility tests

Locally, you can run these tests to catch failures early:

  • spotless: ./gradlew spotlessApply
  • unit tests: ./gradlew build
  • acceptance tests: ./gradlew acceptanceTest
  • integration tests: ./gradlew integrationTest
  • reference tests: ./gradlew ethereum:referenceTests:referenceTests
  • hive tests: Engine or other RPCs modified?

Before, limbs were stored in little-endian.
But to use Arrays.mismatch to our advantage, it is better to have it big-endian.
This commit makes UInt256.java big-endian in limbs.
We still need to migrate all tests and benchmark.

Signed-off-by: Thomas Zamojski <[email protected]>
Also added tests that were failing and now pass.

Signed-off-by: Thomas Zamojski <[email protected]>
Signed-off-by: Thomas Zamojski <[email protected]>
Small cleaning up of the private methods for addition and compareLimbs.
Should be easier for the compiler.

Signed-off-by: Thomas Zamojski <[email protected]>
UInt256 used int[] for limbs, primarily for simplicity, e.g. having the possibility to widen to long.
However, methods exists to work with long[] and no widening. This commit implements long limbs.

To avoid widening, we do:

  1. add: overflow check
  2. mul: native multiplyHigh (compiled to assembly mulq)
  3. div: more complicated, see the gnump division paper.

Signed-off-by: Thomas Zamojski <[email protected]>
@macfarla macfarla moved this to Open PRs in 26.1.0 Release Jan 22, 2026
@macfarla macfarla moved this to In Progress in Performance Jan 22, 2026
@thomas-quadratic thomas-quadratic marked this pull request as draft January 27, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Open PRs
Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants