fixnum icon indicating copy to clipboard operation
fixnum copied to clipboard

BigInt performance comparison

Open creativecreatorormaybenot opened this issue 4 years ago • 7 comments

I am wondering: if I know that I don't need more than 64-bit integers when running on web, should I go for BigInt or for fixnum for best performance?

On native, I will simply use int (as I said, I know I don't need more than 64-bit and on native, int is already 64-bit). But on web, I need to use one of BigInt and fixnum. It would be nice to have a performance comparison between the two.

I think the answer would depend very much on what operations you are using and which browser and browser version the code is running in.

Generally, I would expect fixnum.Int64 to be faster than BigInt, if only because the BigInt version would need the occasional .toSigned(64) to avoid huge values (which would definitely be slower).

It would be better to use stackoverflow for this kind of question, where more people might see the question.

rakudrama avatar Aug 15 '21 01:08 rakudrama

@rakudrama I understand. I feel like the README should have a section for this. And I mean the case where only 64-bit precision is needed, without handling overflows.

If you think this should be investigated on a case by case basis, I can also close this issue.
My main fear was that fixnum is super slow since it is implemented in Dart code.

There is a benchmark in the sdk that you could run. It benchmarks only the parse and toString() operations, but it might be a starting point.

Perhaps you could benchmark your scenario both ways and report your findings here?

rakudrama avatar Aug 15 '21 21:08 rakudrama

https://github.com/dart-lang/fixnum/issues/36#issuecomment-370108579 mentions that BigInt is significantly slower.

My own empirical tests indicate that that's still true. I tried implementing mt19937-64 with both BigInt and Int64, and the BigInt version takes ~2x as long even with compiled to native.

jamesderlin avatar Apr 20 '22 16:04 jamesderlin

@jamesderlin I wonder if you would be willing share your BigInt and Int64 implementations?

rakudrama avatar May 06 '22 17:05 rakudrama

@jamesderlin I wonder if you would be willing share your BigInt and Int64 implementations?

Okay, I've posted them to https://github.com/jamesderlin/dart_mt19937.

  1. Clone the repository.
  2. Check out the unsupported branch.
  3. dart pub get
  4. Run bin/time_mt64.dart.

Running it through the VM, I get times like:

int (signed):   0:00:00.004528
Int64 (signed): 0:00:00.009105
BigInt:         0:00:00.049247

When compiled to an AOT .exe, I get times like:

int (signed):   0:00:00.003894
Int64 (signed): 0:00:00.024484
BigInt:         0:00:00.050144

Interestingly, the Int64 version is way faster with the VM than when AOT-compiled.

jamesderlin avatar May 07 '22 20:05 jamesderlin

Hi James,

Thanks for sharing your code.

From some experimenting with the code I would characterize the relative performance of int:Int64:BigInt as 1:5:25 on JIT VM and 1:12:25 on AOT. I did not call the call method, I rather just called nextInt64 to avoid conversions to BigInt, as I am most interested in the performance of the basic operations. Avoiding the BigInt conversions would make my measured time for int version lower. On dart2js -O4, Int64:BigInt is also 1:5.

/cc @alexmarkov It is interesting that Int64 is 2.5x slower on AOT than JIT. Putting prefer-inline on _masked and _promote recovers most of the difference.

rakudrama avatar May 15 '22 07:05 rakudrama