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

Severe performance regression in neotypes/neotypes #22629

Open
WojciechMazur opened this issue Feb 20, 2025 · 4 comments · May be fixed by #22633
Open

Severe performance regression in neotypes/neotypes #22629

WojciechMazur opened this issue Feb 20, 2025 · 4 comments · May be fixed by #22633
Assignees
Labels
area:transform itype:bug itype:performance regression This worked in a previous version but doesn't anymore

Comments

@WojciechMazur
Copy link
Contributor

WojciechMazur commented Feb 20, 2025

Based on OpenCB build in neotypes/neotypes - build logs

When using Scala 3.6.4-RC1 the compilation finishes under 3-4 minutes
In 3.7.0-NIGHTLY it takes over 3 hours

Bisect (based on 5 minut timeout for building the whole project) points to c65d45d

Needs minimization

@WojciechMazur WojciechMazur added itype:bug itype:performance regression This worked in a previous version but doesn't anymore stat:needs minimization Needs a self contained minimization stat:needs triage Every issue needs to have an "area" and "itype" label labels Feb 20, 2025
@Gedochao Gedochao removed the stat:needs triage Every issue needs to have an "area" and "itype" label label Feb 20, 2025
@Gedochao
Copy link
Contributor

Gedochao commented Feb 20, 2025

cc @som-snytt

c65d45d +2622-1230 lines changed

Ah yes, this will be tricky to pinpoint...

@Gedochao
Copy link
Contributor

@som-snytt I assigned you for now, since you probably have the best chance of finding the root cause, but let me know if we should get someone else to take a look.

@som-snytt
Copy link
Contributor

It turned out to be easy to isolate, as there is a generated source of the form

final def productNamed[A <: Product, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W]
(b: (String, ResultMapper[B]), c: (String, ResultMapper[C]), d: (String, ResultMapper[D]), e: (String, ResultMapper[E]), f: (String, ResultMapper[F]), g: (String, ResultMapper[G]), h: (String, ResultMapper[H]), i: (String, ResultMapper[I]), j: (String, ResultMapper[J]), k: (String, ResultMapper[K]), l: (String, ResultMapper[L]), m: (String, ResultMapper[M]), n: (String, ResultMapper[N]), o: (String, ResultMapper[O]), p: (String, ResultMapper[P]), q: (String, ResultMapper[Q]), r: (String, ResultMapper[R]), s: (String, ResultMapper[S]), t: (String, ResultMapper[T]), u: (String, ResultMapper[U]), v: (String, ResultMapper[V]), w: (String, ResultMapper[W]))
(fun: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W) => A): ResultMapper[A] =
fromFunctionNamed(
b._1, c._1, d._1, e._1, f._1, g._1, h._1, i._1, j._1, k._1, l._1, m._1, n._1, o._1, p._1, q._1, r._1, s._1, t._1, u._1, v._1, w._1
)(fun)(
b._2, c._2, d._2, e._2, f._2, g._2, h._2, i._2, j._2, k._2, l._2, m._2, n._2, o._2, p._2, q._2, r._2, s._2, t._2, u._2, v._2, w._2
)
}

sbt-typelevel turns on parameter checking.

@som-snytt
Copy link
Contributor

som-snytt commented Feb 20, 2025

Apparently a =:=, top of the stack shown:

        at dotty.tools.dotc.core.TypeComparer.loop$1(TypeComparer.scala:1357)
        at dotty.tools.dotc.core.TypeComparer.isMatchingApply$1(TypeComparer.scala:1371)
        at dotty.tools.dotc.core.TypeComparer.compareAppliedType2$1(TypeComparer.scala:1441)
        at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:649)
        at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:573)
        at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:432)
        at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1599)
        at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:229)
        at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:239)
        at dotty.tools.dotc.core.TypeComparer.isSameType(TypeComparer.scala:2359)
        at dotty.tools.dotc.core.TypeComparer.isSubArg$1(TypeComparer.scala:1852)
        at dotty.tools.dotc.core.TypeComparer.recurArgs$1(TypeComparer.scala:1862)
        at dotty.tools.dotc.core.TypeComparer.isSubArgs(TypeComparer.scala:1872)
        at dotty.tools.dotc.core.TypeComparer.loop$1(TypeComparer.scala:1357)
        at dotty.tools.dotc.core.TypeComparer.isMatchingApply$1(TypeComparer.scala:1371)
        at dotty.tools.dotc.core.TypeComparer.compareAppliedType2$1(TypeComparer.scala:1441)
        at dotty.tools.dotc.core.TypeComparer.thirdTry$1(TypeComparer.scala:649)
        at dotty.tools.dotc.core.TypeComparer.secondTry$1(TypeComparer.scala:573)
        at dotty.tools.dotc.core.TypeComparer.firstTry$1(TypeComparer.scala:432)
        at dotty.tools.dotc.core.TypeComparer.recur(TypeComparer.scala:1599)
        at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:229)
        at dotty.tools.dotc.core.TypeComparer.isSubType(TypeComparer.scala:239)
        at dotty.tools.dotc.core.TypeComparer.isSameType(TypeComparer.scala:2359)
        at dotty.tools.dotc.core.TypeComparer$.isSameType(TypeComparer.scala:3400)
        at dotty.tools.dotc.core.Types$Type.$eq$colon$eq(Types.scala:1135)
        at dotty.tools.dotc.transform.CheckUnused$.dotty$tools$dotc$transform$CheckUnused$Resolved$$_$hasRecord$$anonfun$1(CheckUnused.scala:470)
        at dotty.tools.dotc.transform.CheckUnused$Resolved$$Lambda/0x00007f725f4ca100.apply(Unknown Source)
        at scala.collection.immutable.List.find(List.scala:414)
        at dotty.tools.dotc.transform.CheckUnused$Resolved.hasRecord(CheckUnused.scala:470)
        at dotty.tools.dotc.transform.CheckUnused.resolveUsage(CheckUnused.scala:340)
        at dotty.tools.dotc.transform.CheckUnused.transformSelect(CheckUnused.scala:78)
        at dotty.tools.dotc.transform.CheckUnused.transformSelect(CheckUnused.scala:67)
        at dotty.tools.dotc.transform.MegaPhase.goSelect(MegaPhase.scala:636)

for types such as

CMP neotypes.mappers.ResultMapper[(((((((((B, C), D), E), F), G), H), I), J), K)] =:= neotypes.mappers.ResultMapper[(
  (
    (((((((((((((((B, C), D), E), F), G), H), I), J), K), L), M), N), O), P), Q)
      ,
  R),
S)]

This is comparing prefixes of a selection and import, which was the motivating problem.

Edit: per the PR, it should not have been performing these comparisons, so it is moot whether they are expensive.

@som-snytt som-snytt linked a pull request Feb 20, 2025 that will close this issue
@Gedochao Gedochao added area:transform and removed stat:needs minimization Needs a self contained minimization labels Feb 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:transform itype:bug itype:performance regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants