scala-js icon indicating copy to clipboard operation
scala-js copied to clipboard

Do not use `Double` arithmetics in `Integer.parseInt()`.

Open sjrd opened this issue 10 months ago • 5 comments

Only use Int arithmetics. To detect overflow, we precompute a table of the maximum string length for each radix.

Int arithmetics is faster than Double arithmetics. The previous code used Doubles to have a concise way of detecting the overflow, which is not bad on JS engines. Given a cached overflow detection mechanism, resorting to Doubles is not necessary anymore.

sjrd avatar Jun 06 '25 14:06 sjrd

I was wondering if you could take a peek and make any recommendations based on this work? https://github.com/scala-native/scala-native/blob/main/javalib/src/main/scala/java/lang/Integer.scala

ekrich avatar Jun 06 '25 17:06 ekrich

Those are fine implementations, but not as good as what's in this PR. In particular, caching the max is worthwhile, because divisions by non-constants are expensive. Otherwise it's pretty similar.

sjrd avatar Jun 06 '25 18:06 sjrd

I'll review fully, but could you amend the description to include some information about why this is better?

gzm0 avatar Jun 07 '25 06:06 gzm0

I'll review fully, but could you amend the description to include some information about why this is better?

I added a paragraph in the PR description. I'll integrate it in the commit message next time I amend/rebase/etc. The short answer is "it's faster" ;)

Edit: done

sjrd avatar Jun 07 '25 07:06 sjrd

So, after a day spent exploring many alternatives and benchmarking them both on JS and Wasm, eventually I found the best of all worlds: it's faster than before on both engines; it stays as small as it is today; and it doesn't use any lookup table.

The only downside is that we have two different implementations for parseInt and parseUnsignedInt. That does not increase code size, because previously the common implementation was inlined in each to constant-fold the signed parameter anyway.

sjrd avatar Jun 19 '25 14:06 sjrd