Skip to content

Instantly share code, notes, and snippets.

@wemeetagain
Last active February 8, 2023 05:22
Show Gist options
  • Save wemeetagain/73a92ceb5f942b940898eea0aa578546 to your computer and use it in GitHub Desktop.
Save wemeetagain/73a92ceb5f942b940898eea0aa578546 to your computer and use it in GitHub Desktop.
BigInt vs BN.js vs number benchmark
const Benchmark = require('benchmark')
const BN = require('bn.js')
const suite = new Benchmark.Suite
// native numbers
let num_a, num_b
// BN.js numbers
let bn_a, bn_b
// native BigInt numbers
let bi_a, bi_b
const randSmallInt = () => Math.floor(Math.random() * 2**24)
const randBiggerInt = () => "" + Math.floor(Math.random() * 2**48) + Math.floor(Math.random() * 2**48)
const genNewSmallInputs = () => {
num_a = randSmallInt()
num_b = randSmallInt()
bn_a = new BN(num_a)
bn_b = new BN(num_b)
bi_a = BigInt(num_a)
bi_b = BigInt(num_b)
}
const genNewBiggerInputs = () => {
const str_a = randBiggerInt()
const str_b = randBiggerInt()
bn_a = new BN(str_a)
bn_b = new BN(str_b)
bi_a = BigInt(str_a)
bi_b = BigInt(str_b)
}
const options = {
onStart: genNewSmallInputs,
onCycle: genNewSmallInputs,
}
const bigOptions = {
onStart: genNewBiggerInputs,
onCycle: genNewBiggerInputs,
}
suite
.add('number#add', () => num_a + num_b, options)
.add('number#sub', () => num_a - num_b, options)
.add('number#div', () => Math.floor(num_a / num_b), options)
.add('number#mul', () => num_a * num_b, options)
.add('BN#add', () => bn_a.add(bn_b), options)
.add('BN#sub', () => bn_a.sub(bn_b), options)
.add('BN#div', () => bn_a.div(bn_b), options)
.add('BN#mul', () => bn_a.mul(bn_b), options)
.add('BN#add (n > 2**64)', () => bn_a.add(bn_b), bigOptions)
.add('BN#sub (n > 2**64)', () => bn_a.sub(bn_b), bigOptions)
.add('BN#div (n > 2**64)', () => bn_a.div(bn_b), bigOptions)
.add('BN#mul (n > 2**64)', () => bn_a.mul(bn_b), bigOptions)
.add('BigInt#add', () => bi_a + bi_b, options)
.add('BigInt#sub', () => bi_a - bi_b, options)
.add('BigInt#div', () => bi_a / bi_b, options)
.add('BigInt#mul', () => bi_a * bi_b, options)
.add('BigInt#add (n > 2**64)', () => bi_a + bi_b, bigOptions)
.add('BigInt#sub (n > 2**64)', () => bi_a - bi_b, bigOptions)
.add('BigInt#div (n > 2**64)', () => bi_a / bi_b, bigOptions)
.add('BigInt#mul (n > 2**64)', () => bi_a * bi_b, bigOptions)
.on('cycle', (evt) => console.log(String(evt.target)))
.run({async: true})
/*
$ node --version
v10.15.1
$ node bigint_vs_bn_vs_number.js
number#add x 166,680,025 ops/sec ±0.44% (92 runs sampled)
number#sub x 165,210,303 ops/sec ±3.40% (85 runs sampled)
number#div x 170,510,248 ops/sec ±0.63% (90 runs sampled)
number#mul x 163,694,640 ops/sec ±1.42% (91 runs sampled)
BN#add x 39,612,100 ops/sec ±0.93% (88 runs sampled)
BN#sub x 17,208,730 ops/sec ±1.63% (78 runs sampled)
BN#div x 18,231,185 ops/sec ±7.30% (65 runs sampled)
BN#mul x 59,932,956 ops/sec ±1.53% (87 runs sampled)
BN#add (n > 2**64) x 24,662,255 ops/sec ±0.40% (92 runs sampled)
BN#sub (n > 2**64) x 12,091,169 ops/sec ±0.95% (86 runs sampled)
BN#div (n > 2**64) x 5,488,495 ops/sec ±20.32% (39 runs sampled)
BN#mul (n > 2**64) x 8,006,484 ops/sec ±1.04% (88 runs sampled)
BigInt#add x 19,542,139 ops/sec ±1.06% (86 runs sampled)
BigInt#sub x 23,921,336 ops/sec ±0.82% (91 runs sampled)
BigInt#div x 25,085,055 ops/sec ±3.21% (74 runs sampled)
BigInt#mul x 17,035,338 ops/sec ±0.86% (88 runs sampled)
BigInt#add (n > 2**64) x 18,395,735 ops/sec ±0.98% (86 runs sampled)
BigInt#sub (n > 2**64) x 22,845,381 ops/sec ±0.86% (92 runs sampled)
BigInt#div (n > 2**64) x 14,991,941 ops/sec ±17.13% (47 runs sampled)
BigInt#mul (n > 2**64) x 12,937,009 ops/sec ±0.38% (90 runs sampled)
*/
@paulmillr
Copy link

M1 / macos 12 clearly shows that native is the way to go

number#add x 155,656,459 ops/sec ±0.10% (99 runs sampled)
number#sub x 155,753,173 ops/sec ±0.05% (99 runs sampled)
number#div x 154,217,754 ops/sec ±0.06% (99 runs sampled)
number#mul x 155,438,698 ops/sec ±0.07% (99 runs sampled)
BN#add x 64,737,502 ops/sec ±0.12% (100 runs sampled)
BN#sub x 46,915,961 ops/sec ±0.15% (99 runs sampled)
BN#div x 35,716,549 ops/sec ±5.80% (76 runs sampled)
BN#mul x 82,624,968 ops/sec ±0.06% (101 runs sampled)
BN#add (n > 2**64) x 40,000,823 ops/sec ±0.05% (100 runs sampled)
BN#sub (n > 2**64) x 31,371,952 ops/sec ±0.05% (99 runs sampled)
BN#div (n > 2**64) x 10,035,585 ops/sec ±27.60% (23 runs sampled)
BN#mul (n > 2**64) x 11,929,530 ops/sec ±0.17% (99 runs sampled)
BigInt#add x 153,910,907 ops/sec ±0.08% (100 runs sampled)
BigInt#sub x 154,096,166 ops/sec ±0.07% (102 runs sampled)
BigInt#div x 36,939,002 ops/sec ±3.55% (85 runs sampled)
BigInt#mul x 33,150,552 ops/sec ±0.10% (100 runs sampled)
BigInt#add (n > 2**64) x 145,474,616 ops/sec ±2.68% (97 runs sampled)
BigInt#sub (n > 2**64) x 108,359,439 ops/sec ±0.73% (95 runs sampled)
BigInt#div (n > 2**64) x 11,581,540 ops/sec ±20.28% (31 runs sampled)
BigInt#mul (n > 2**64) x 26,503,851 ops/sec ±0.95% (85 runs sampled)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment