decimo

Benchmarks

2026-10-16 · main ad7db3d · arm64, macOS-26.6.2-arm64-arm-64bit-Mach-O

Mojo 1.1.0 (8189361e) · CPython 3.14.6 · libmpdec 4.0.1 and GMP 6.3.0, both linked from C

Each figure is the minimum over several rounds, on an idle machine. Regenerate with pixi run benchdoc.

BigDecimal

Operands of digits decimal digits at working precision, so that precision grows with the operands. libmpdec is the C library behind CPython’s decimal, timed without the interpreter. round drops the low half of the operand; parse builds the value from its string.

Verified this run: decimo and libmpdec produce the same 2000-digit product from the same 1000-digit operands.

Digits / precision Operation decimo libmpdec   CPython decimal  
9 / 28 add 11.2 ns 35.3 ns 3.16× faster 47.1 ns 4.21× faster
9 / 28 subtract 12.0 ns 34.8 ns 2.91× faster 46.9 ns 3.92× faster
9 / 28 multiply 13.5 ns 27.3 ns 2.03× faster 44.8 ns 3.33× faster
9 / 28 divide 59.5 ns 51.2 ns 1.16× slower 69.6 ns 1.17× faster
9 / 28 round 7.8 ns 32.5 ns 4.19× faster 71.5 ns 9.21× faster
9 / 28 parse 53.8 ns 42.2 ns 1.27× slower 82.1 ns 1.53× faster
1,000 / 1,000 add 50.1 ns 116.5 ns 2.32× faster 112.5 ns 2.24× faster
1,000 / 1,000 subtract 60.6 ns 97.5 ns 1.61× faster 86.1 ns 1.42× faster
1,000 / 1,000 multiply 1.07 µs 9.09 µs 8.51× faster 9.89 µs 9.26× faster
1,000 / 1,000 divide 5.82 µs 14.51 µs 2.50× faster 15.68 µs 2.70× faster
1,000 / 1,000 round 51.4 ns 101.5 ns 1.97× faster 124.7 ns 2.43× faster
1,000 / 1,000 parse 1.26 µs 1.65 µs 1.30× faster 2.06 µs 1.63× faster
100,000 / 100,000 add 2.50 µs 6.00 µs 2.40× faster 6.77 µs 2.71× faster
100,000 / 100,000 subtract 3.00 µs 3.70 µs 1.23× faster 4.05 µs 1.35× faster
100,000 / 100,000 multiply 1.85 ms 2.92 ms 1.58× faster 3.06 ms 1.66× faster
100,000 / 100,000 divide 4.66 ms 14.22 ms 3.05× faster 14.81 ms 3.18× faster
100,000 / 100,000 round 2.65 µs 4.25 µs 1.60× faster 4.82 µs 1.82× faster
100,000 / 100,000 parse 119.50 µs 160.40 µs 1.34× faster 177.10 µs 1.48× faster
1,000,000 / 1,000,000 add 24.50 µs 58.50 µs 2.39× faster 69.38 µs 2.83× faster
1,000,000 / 1,000,000 subtract 30.00 µs 35.50 µs 1.18× faster 40.88 µs 1.36× faster
1,000,000 / 1,000,000 multiply 25.30 ms 30.76 ms 1.22× faster 32.33 ms 1.28× faster
1,000,000 / 1,000,000 divide 123.80 ms 161.11 ms 1.30× faster 169.77 ms 1.37× faster
1,000,000 / 1,000,000 round 29.50 µs 45.50 µs 1.54× faster 43.81 µs 1.49× faster
1,000,000 / 1,000,000 parse 1.20 ms 1.58 ms 1.32× faster 2.02 ms 1.68× faster

sqrt, exp, ln, power

A fixed set, chosen before the results were seen. 2.3456789, and ** 1.5 for power. 100 000 digits is left out because mpd_exp needs 82 seconds there and mpd_ln 239 seconds.

Precision Operation decimo libmpdec  
28 sqrt 374.6 ns 902.5 ns 2.41× faster
28 exp 5.13 µs 4.59 µs 1.12× slower
28 ln 3.01 µs 13.28 µs 4.42× faster
28 power 9.28 µs 36.61 µs 3.95× faster
100 sqrt 2.13 µs 4.16 µs 1.96× faster
100 exp 6.61 µs 15.18 µs 2.30× faster
100 ln 10.03 µs 40.42 µs 4.03× faster
100 power 19.37 µs 84.42 µs 4.36× faster
1,000 sqrt 21.82 µs 232.02 µs 10.63× faster
1,000 exp 237.69 µs 4.81 ms 20.25× faster
1,000 ln 157.59 µs 5.56 ms 35.30× faster
1,000 power 313.32 µs 11.33 ms 36.16× faster
10,000 sqrt 528.50 µs 22.66 ms 42.87× faster
10,000 exp 15.46 ms 1.983 s 128.26× faster
10,000 ln 8.43 ms 3.527 s 418.58× faster
10,000 power 24.43 ms 5.020 s 205.46× faster

BigInt against GMP and CPython’s int

GMP is the reference implementation for big integers and the harder opponent, timed in C. CPython’s integers can only be reached through the interpreter, so those include its overhead — read the large sizes as the real ones. Division is 2n-by-n; two operands of the same width would give a one-digit quotient and measure nothing.

An mpz_t always lives on the heap. Adding two 100-digit values costs GMP 19.3 ns into a fresh result against 5.2 ns into a reused one, so most of it is malloc and free. decimo keeps small values inside the struct, which is why it leads at the small end and trails at the large one, where the algorithm is all that is left.

Digits Operation decimo GMP   CPython int  
10 add 5.9 ns 17.0 ns 2.85× faster 23.4 ns 3.94× faster
10 multiply 7.4 ns 16.6 ns 2.25× faster 29.1 ns 3.94× faster
10 floor divide 11.3 ns 24.1 ns 2.14× faster 52.6 ns 4.66× faster
10 sqrt 2.7 ns 16.4 ns 6.16× faster 30.4 ns 11.42× faster
100 add 7.2 ns 19.3 ns 2.70× faster 29.3 ns 4.10× faster
100 multiply 41.8 ns 29.9 ns 1.40× slower 119.5 ns 2.86× faster
100 floor divide 117.2 ns 83.1 ns 1.41× slower 317.8 ns 2.71× faster
100 sqrt 126.2 ns 61.0 ns 2.07× slower 335.4 ns 2.66× faster
1,000 add 33.4 ns 29.2 ns 1.14× slower 94.5 ns 2.83× faster
1,000 multiply 1.06 µs 627.8 ns 1.69× slower 5.72 µs 5.38× faster
1,000 floor divide 1.96 µs 1.33 µs 1.47× slower 13.73 µs 6.99× faster
1,000 sqrt 1.65 µs 391.6 ns 4.22× slower 4.74 µs 2.87× faster
10,000 add 180.0 ns 150.0 ns 1.20× slower 861.2 ns 4.78× faster
10,000 multiply 45.56 µs 20.39 µs 2.23× slower 280.83 µs 6.16× faster
10,000 floor divide 92.19 µs 52.16 µs 1.77× slower 575.90 µs 6.25× faster
10,000 sqrt 24.32 µs 8.61 µs 2.83× slower 289.32 µs 11.90× faster
100,000 add 1.75 µs 1.45 µs 1.21× slower 8.60 µs 4.91× faster
100,000 multiply 1.23 ms 446.25 µs 2.76× slower 9.17 ms 7.44× faster
100,000 floor divide 3.81 ms 1.16 ms 3.27× slower 18.93 ms 4.97× faster
100,000 sqrt 984.85 µs 312.05 µs 3.16× slower 8.81 ms 8.95× faster
1,000,000 add 19.00 µs 13.50 µs 1.41× slower 86.17 µs 4.54× faster
1,000,000 multiply 24.78 ms 6.49 ms 3.82× slower 387.56 ms 15.64× faster
1,000,000 floor divide 108.03 ms 17.13 ms 6.31× slower 784.35 ms 7.26× faster
1,000,000 sqrt 32.39 ms 6.05 ms 5.35× slower 359.62 ms 11.10× faster

pi()

Each measurement in a fresh process, since mpmath and MPFR cache the constant. Includes conversion to a decimal string, for every library.

The two decimo columns compute the same series through the same integer code and differ only in where the digits end up; BigFloat is asked for the computation its own cache would have missed on, so that it is measured cold like the rest.

Digits decimo (BigDecimal) decimo (BigFloat) mpmath + GMP MPFR mpmath (pure Python)
100 2.49 µs 3.25 µs 53.79 µs 50.62 µs 37.42 µs
1,000 22.33 µs 23.94 µs 120.75 µs 72.62 µs 176.96 µs
10,000 722.60 µs 715.30 µs 936.12 µs 748.71 µs 6.29 ms
100,000 27.24 ms 26.61 ms 16.12 ms 24.02 ms 191.05 ms
1,000,000 720.61 ms 719.20 ms 275.24 ms 440.40 ms 8.869 s