Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #19907: Skip soft unions in widenSingle of widenInferred #19995

Merged
merged 4 commits into from
Mar 25, 2024

Conversation

noti0na1
Copy link
Member

@noti0na1 noti0na1 commented Mar 20, 2024

Fix #19907.

If the inferred type inst is too large, the subtype check for bound in widenSingle can be expensive
due to comparisons between large union types, so we avoid it by skipping soft unions in the first step.
Singletons of soft unions are widened when we widenUnion now.

@noti0na1 noti0na1 changed the title [WIP] Skip widenSingletons in widenInferred if the inferred type is too large Fix #19907: Skip widenSingletons in widenInferred if the inferred type is too large Mar 21, 2024
@noti0na1 noti0na1 changed the title Fix #19907: Skip widenSingletons in widenInferred if the inferred type is too large Fix #19907: Skip widenSingle in widenInferred if the inferred type is too large Mar 21, 2024
@noti0na1 noti0na1 requested a review from odersky March 21, 2024 00:25
@noti0na1
Copy link
Member Author

test performance please

@noti0na1 noti0na1 requested a review from smarter March 21, 2024 00:31
@mbovel
Copy link
Member

mbovel commented Mar 21, 2024

test performance please

@dottybot
Copy link
Member

performance test scheduled: 149 job(s) in queue, 1 running.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/19995/ to see the changes.

Benchmarks is based on merging with main (a36849f)

val widenedFromUnion = widenOr(widenedFromSingle)
val widenedFromUnion =
if widenUnions && typeSize(inst) > 64 then
// If the inferred type `inst` is too large, the subtype check for `bound` in `widenSingle`
Copy link
Contributor

Choose a reason for hiding this comment

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

Very useful diagnosis! I think we can even go further: If we have widenUnions then we never need to widen singletons in soft unions, since we will do an OrDominator afterwards, and this is the same for original or widen types. We don't even need a size limit for this.

I'll push a commit that tries this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Correction: It does not work since we sometimes leave original orType if it is transparent, and then we should ideally widen singleton types.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could fix it and account for transparent unions. See latest commit.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I updated the title.

@noti0na1 noti0na1 changed the title Fix #19907: Skip widenSingle in widenInferred if the inferred type is too large Fix #19907: Skip soft unions in widenSingle of widenInferred Mar 22, 2024
@noti0na1
Copy link
Member Author

test performance please

@dottybot
Copy link
Member

performance test scheduled: 139 job(s) in queue, 1 running.

@dottybot
Copy link
Member

Performance test finished successfully:

Visit https://dotty-bench.epfl.ch/19995/ to see the changes.

Benchmarks is based on merging with main (a36849f)

@odersky odersky assigned smarter and unassigned odersky Mar 23, 2024
@odersky
Copy link
Contributor

odersky commented Mar 23, 2024

Passing on to @smarter for final comments or approval.

Copy link
Member

@smarter smarter left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM.

@smarter smarter assigned odersky and unassigned smarter Mar 25, 2024
@noti0na1 noti0na1 merged commit 198750b into scala:main Mar 25, 2024
19 checks passed
@noti0na1 noti0na1 deleted the fix-19907 branch March 25, 2024 17:41
@odersky odersky mentioned this pull request Mar 27, 2024
@Kordyjan Kordyjan added this to the 3.4.2 milestone Mar 28, 2024
odersky added a commit that referenced this pull request Mar 29, 2024
Replace mergeIfSuper by a different algorithm that is more efficient.
We drop or-summands in both arguments of a lub that are subsumed by the
other.
This avoids expensive recursive calls to lub or expensive comparisons
with union types on the right.

I tested the previous performance regression #19907 with the new
algorithm, and without the changes in #19995 that avoid a slow lub.
Where previously it took minutes it now compiles fast.

Specifically, we get for i19907_slow_1000_3.scala: 2.9s with the
optimizations in #19995, 3.3s with just this PR. And for
i19907_slow_1000_4.scala: 3.9s with the optimizations in #19995, 4.5s
with just this PR. So the optimizations in #19995 are much less critical
now since lubs are much faster. Still, it's probably worthwhile to leave
them in in case there is a humongous program that stresses lubs even
more.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Exponential growth of compilation time with number of inferred types of List element
6 participants