BigInt

Bun has a bigint size limitation. It's 1_048_575 bits (1024 ** 2) or 131_072 Bytes.

Size Constraints

The module.f.mjs exports two constants documenting this limit:

  • maxBits = 1,048,575n — the maximum number of bits in a bigint value
  • maxBytes = 131,072n — the maximum file size in bytes (equivalent to maxBits ÷ 8)

This limit applies to all bigint-backed types, including bit_vec and ReadFile effects. The ReadFile effect enforces this limit on file reads to ensure cross-runtime compatibility — files larger than 131,072 bytes will be rejected with a validation error.

Benchmarks

Aligned Shift (2025/01/11)

For big numbers, about 2n ** 1_000_000n:

FrameworkstrBinLog2strHexLog2str32Log2oldLog2clz32Log2m1023log2log2
Bun2281849702181010001291643
Deno 240921051846501297214183
Deno 140701062858522312222186
Node 23406511521015499278233168
Node 22420812661070568332265191
Node 20418412311083624333261185
Node 18460414011279770472360281
Node 16414312221144735471313282

For small numbers, about 2n ** 1_000n:

FrameworkstrBinLog2strHexLog2str32Log2oldLog2clz32Log2m1023log2log2
Bun22561381130140191972721706
Deno 229469718271800887471472
Deno 130049627981622828456432
Node 23297510558761819945514510
Node 22317410718931812933495477
Node 203144109890518331030587582
Node 184292155514324631241510031016
Node 163360157114534759252610581051

Browser Test

For big numbers, about 2n ** 1_000_000n:

BrowserCPUstrBinLog2strHexLog2str32Log2oldLog2clz32Log2m1023log2log2
ChromeAMD23166285321173798525514
ChromeM11228342280319220169138
FirefoxAMD32866515303037218214321370
FirefoxM1152039933917931332825831
SafariM11311364285318216208130

For small numbers, about 2n ** 1_000n:

BrowserCPUstrBinLog2strHexLog2str32Log2oldLog2clz32Log2m1023log2log2
ChromeAMD213393280521701189595587
ChromeM112274914161047540285282
FirefoxAMD2221100792824951294504499
FirefoxM113195925461714901341340
SafariM1182178472320991074456451

New log2 based on Math.log2 and str32Log2 (2025/01/10)

See also https://medium.com/@sergeyshandar/improving-the-log2-algorithm-for-bigint-in-javascript-7e5692e7bf0b?sk=9ac18367f61b524704cc8d82707aed3d

For big numbers, about 2n ** 1_000_000n:

FrameworkstrBinLog2strHexLog2str32Log2oldLog2clz32Log2log2
Bun2071731631182711951110
Deno 23720970788506307206
Deno 13710966782488292204
Node 2338031073947534317226
Node 2238821073967479265222
Node 2038551118992494280217
Node 18383211791058514280229
Node 16378111181037672430281

For small numbers, about 2n ** 1_000n:

FrameworkstrBinLog2strHexLog2str32Log2oldLog2clz32Log2log2
Bun25391353129337331885699
Deno 230679757911662877452
Deno 130529888281656856456
Node 23304610478981795926538
Node 22312810498781845932500
Node 20309510889351796940566
Node 1833991506139144972305970
Node 16336815611427491625931069

Browser Test

For big numbers, about 2 ** 1_000_000:

BrowserCPUstrBinLog2strHexLog2str32Log2oldLog2clz32Log2log2
ChromeAMD23607155321190807551
ChromeM11235349283324226171
FirefoxAMD3189588529291221651443
FirefoxM1151640133817991339847
SafariM11650369299318215203

For small numbers, 1 .. 2 ** 2_000:

BrowserCPUstrBinLog2strHexLog2str32Log2oldLog2clz32Log2log2
ChromeAMD201088978122951210593
ChromeM112274954171055539285
FirefoxAMD2117985105624671263503
FirefoxM1132659454119671013348
SafariM1180878474120131108466

Note: the benchmark was changed since 2024 and runs more tests. Compare only relative numbers.

newLog2 (32 based) versus others (2024/12/27)

Frameworkstr binstr hexold log2log2
Bun994.3296458.66331038.7439669.9755
Deno 21884.6942485.5894240.4493143.2709
Deno 11878.0000494.0000268.0000168.0000
Node 231855.9599558.6656241.5325138.5897
Node 221863.8143533.0014225.9727121.1032
Node 201938.3770561.1601253.4389129.6232
Node 181888.5652590.6440243.8712134.0867
Node 161901.8710560.1892339.8360213.6341

The new log2 wins on Deno and Node (V8) but slightly loses on Bun (WebKit).

https://github.com/functionalscript/functionalscript/actions/runs/12521052013/job/34927599441?pr=346

Browser Test

The table below was measured once per browser, by hand, on a page written for it and pasted here. That page is gone: demo.f.mjs runs the same comparison on this module's own page, in whatever browser is reading it, so the numbers a reader cares about are the ones their machine produces rather than the ones someone recorded in 2025.

BrowserCPUstr binstr hexold log2log2
ChromeAMD1214334532369
ChromeM1673176162106
FirefoxAMD179732317041267
FirefoxM1788201910683
SafariM1712180160106

Minus versus Not

Frameworkminus -not ~
Bun86.26996780.372970
Deno 118.75481059.498217
Deno 217.26248657.157273
Node 1670.350582121.023162
Node 1861.03946399.369215
Node 2016.90869563.335552
Node 2219.54664459.034978
Node 2318.24669758.825815

- wins.

Old Benchmarks

log2 versus toString (2024/11/25)

Frameworklog2(x)x.toString(2).length
Bun1.7816812.079615
Deno 10.7103441.917003
Deno 20.9866022.286932
Node 161.5211502.330505
Node 181.3930062.312573
Node 201.0553152.320039
Node 220.9830752.336697
Node 230.6999601.872965

log2 wins.

Demo

Seven ways to find the highest set bit of a bigint (its base-2 logarithm, rounded down), timed in the browser you are reading this in. The first is this module's log2; the other six are the older and alternative versions it was chosen over.

Each one runs on every power of two up to the exponent below, and on the number just below each, and every result is checked: a candidate that is fast but gives a wrong result says so instead of showing a time. The work grows with the square of the exponent, so doubling it takes about four times as long.

log2 of every power of two below 2^, and the number below each.

Emergent Testing

Idle. Press Run to start the suite.

  • ./demo.f.mjs
  • ./from_number/proof.f.mjs
  • ./proof.f.mjs