juno
juno copied to clipboard
Optimize the DivMod function
The divMod
function in points.go is a major bottleneck when applying state diffs to the local database. Right now, we are using big.Int
s, which are inefficient.
Solution
An implementation of Lehmer's GCD algorithm using the felt package. This is the same algorithm that the big
package uses, but our felt.Felt
s should vastly outperform big.Int
s.
Note that we don't want to use the modular arithmetic functions provided by the felt package when computing the GCD. Since our felts are just [4]uint64
underneath, we can use the very fast uint256 library instead.
Alternatives Considered
I have tried to implement this using gmp.Int
as a drop-in replacement for big.Int
, but it was slower than using big.Int
s directly (probably due to the increase in allocations from felt -> big.Int -> gmp.Int -> big.Int -> felt).
I also considered porting the igcdex
function from the Python reference implementation, but it implements Euclid's GCD algorithm, which is slower than Lehmer's algorithm for big numbers.
some of the discussions we had on this -
- The Inverse function provided by the
felt
package doesn't work as a replacement for Lehmer's gcd function to compute inverses, since it computes the results modulo p, which changes the results of the product - The problem with implementing Lehmer's gcd for felts is that we still need a way to handle negative values with felts. Maybe, this can be achieved by using a new variable to keep track of the felt's sign whenever it under/over flows.