Skip to content

Streamline the initialization path of Range.#11098

Merged
lrytz merged 2 commits intoscala:2.13.xfrom
sjrd:range-unsigned-arith
Aug 29, 2025
Merged

Streamline the initialization path of Range.#11098
lrytz merged 2 commits intoscala:2.13.xfrom
sjrd:range-unsigned-arith

Conversation

@sjrd
Copy link
Copy Markdown
Member

@sjrd sjrd commented Aug 7, 2025

This PR upstreams scala-js/scala-js#5176 from Scala.js. We generally streamline the initialization paths of Ranges by using unsigned Int arithmetics. When branches are needed, we make them depend on isInclusive and/or step if possible, since those are likely constant or predictable in practice.

For Scala.js, these changes were really good, because Long operations are particularly expensive. Moreover, the inliner and constant-folder are such that common cases can fold away virtually all the computations of the new implementation. I would assume that the JVM is at least equally capable.

I was hoping to find existing benchmarks for Range in test/benchmarks, but there were none. @Ichoran, I guess you are, to this day, the most knowledgeable about Range performance, given 00d3f10. Any suggestion?

sjrd added 2 commits August 7, 2025 13:42
Extract branches to be mostly dependent on `isInclusive` and
`step >= 0`. These are often constant, and when they're not
statically constant, they are probably predictable anyway.

This commit upstreams
scala-js/scala-js@a5337ed
from Scala.js.
Previously, `Range` used a number of intermediate operations on
`Long`s to avoid overflow. We can streamline a lot of code by
using unsigned `Int` arithmetics. In particular, there is only 1
division in the initialization path, instead of 3.

Although the fields have not changed, the content of
`numRangeElements` is more strict for overfull ranges. This means
that deserializing an overfull range from a previous version would
not be safe. This is why we bump the SerialVersionUID.

This commit upstreams
scala-js/scala-js@d972218
from Scala.js.
@sjrd sjrd requested a review from lrytz August 7, 2025 12:22
@sjrd sjrd requested a review from a team as a code owner August 7, 2025 12:22
@scala-jenkins scala-jenkins added this to the 2.13.17 milestone Aug 7, 2025
@SethTisue SethTisue added library:collections PRs involving changes to the standard collection library performance the need for speed. usually compiler performance, sometimes runtime performance. labels Aug 7, 2025
@Ichoran
Copy link
Copy Markdown
Contributor

Ichoran commented Aug 8, 2025

I am pretty sure I was testing the different variants with Thyme, but I no longer have a recollection of what the different tests were.

In general, the operations I see being used here are ones that I find to give pretty good performance, so it seems quite plausible that this would be a win.

I don't have any specific advice about testing Range; I don't remember what I did, aside from the usual general strategy of picking tests where the new code is heavily stressed. I don't have the time at the moment. (I use JMH these days, usually launched with scala-cli if it's a small test just to validate my ideas about something being fast or not-slow.)

Copy link
Copy Markdown
Member

@lrytz lrytz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Do we have or did you write on the Scala.js side some tests for the corner cases? LGTM, but it pretty subtle code :)

@sjrd
Copy link
Copy Markdown
Member Author

sjrd commented Aug 29, 2025

Existing tests seemed to be enough. Some relevant links:

range-unit, in particular, covers a large number of start/end/step combinations for corner cases.

@lrytz
Copy link
Copy Markdown
Member

lrytz commented Aug 29, 2025

Thank you - I only saw the junit test on a quick search.

@lrytz lrytz merged commit d66a09d into scala:2.13.x Aug 29, 2025
4 checks passed
@sjrd sjrd deleted the range-unsigned-arith branch August 29, 2025 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

library:collections PRs involving changes to the standard collection library performance the need for speed. usually compiler performance, sometimes runtime performance.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants