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

perf(compiler): Inliner optimization [LNG-322] #1047

Merged
merged 17 commits into from
Jan 22, 2024
Merged

Conversation

DieMyst
Copy link
Member

@DieMyst DieMyst commented Jan 17, 2024

Description

Inliner works slow on big projects.

Proposed Changes

Mangler works unefficiently, rewrite it with effective alghorithm.

Implementation Details

Also, air builder was rewritten on StringBuilder for effectiveness.

Checklist

  • Corresponding issue has been created and linked in PR title.
  • Proposed changes are covered by tests.
  • Documentation has been updated to reflect the changes (if applicable).
  • I have self-reviewed my code and ensured its quality.
  • I have added/updated necessary comments to aid understanding.

Reviewer Checklist

  • Tests have been reviewed and are sufficient to validate the changes.
  • Documentation has been reviewed and is up to date.
  • Any questions or concerns have been addressed.

@DieMyst DieMyst changed the title Inliner optimization perf(compiler): Inliner optimization [LNG-322] Jan 17, 2024
Copy link

linear bot commented Jan 17, 2024

@DieMyst DieMyst added the e2e Run e2e workflow label Jan 19, 2024
@DieMyst DieMyst closed this Jan 19, 2024
@DieMyst DieMyst reopened this Jan 19, 2024
@DieMyst DieMyst marked this pull request as ready for review January 19, 2024 10:39
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you restore this file please?

@@ -11,7 +11,7 @@ class ImportsSpec extends AnyFlatSpec with ScalaCheckPropertyChecks with Matcher

implicit override val generatorDrivenConfig =
// Tests here are lightweight, so we can afford to run more of them
PropertyCheckConfiguration(minSuccessful = 500, sizeRange = 64)
PropertyCheckConfiguration(minSuccessful = 50, sizeRange = 32)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why lower those values?


def findNewName(introduce: String): State[S, String] =
findNewNames(Set(introduce)).map(_.getOrElse(introduce, introduce))
def getForbiddenNames: State[S, ManglerState]
Copy link
Contributor

@InversionSpaces InversionSpaces Jan 19, 2024

Choose a reason for hiding this comment

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

Is it used somewhere outside implementation and tests?
Maybe return actually set of forbidden names, rename the method to smth like getState or totally remove this method from the interface?

Comment on lines 38 to 41
getForbiddenNames.flatMap(forbidden =>
val (newState, newNames) = forbidden.findNewNames(introduce)
State.modify[ManglerState](_ => newState).map(_ => newNames)
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
getForbiddenNames.flatMap(forbidden =>
val (newState, newNames) = forbidden.findNewNames(introduce)
State.modify[ManglerState](_ => newState).map(_ => newNames)
)
State.apply(_.findNewNames(introduce))

Comment on lines 11 to 16
val mangler = Mangler.Simple

val a = for {
_ <- mangler.forbid(Set("first", "second"))
fn <- mangler.getForbiddenNames
} yield fn
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the test?

}
}

object Mangler {
def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler

implicit object Simple extends Mangler[Set[String]] {
val getForbiddenNames: State[Set[String], Set[String]] = State.get
implicit object Simple extends Mangler[ManglerState] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
implicit object Simple extends Mangler[ManglerState] {
given Mangler[ManglerState] with {

and then Mangler.Simple -> Mangler[ManglerState]

def forbid(names: Set[String]): State[R, Unit] =
self.forbid(names).transformS(f, g)

def findAndForbidNames(introduce: Set[String]): State[R, Map[String, String]] =
self.findAndForbidNames(introduce).transformS(f, g)
}
}

object Mangler {
def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
def apply[S](implicit mangler: Mangler[S]): Mangler[S] = mangler
def apply[S](using mangler: Mangler[S]): Mangler[S] = mangler


val results = for {
res <- mangler.findAndForbidNames(Set("first", "second"))
fn <- mangler.getForbiddenNames
Copy link
Contributor

Choose a reason for hiding this comment

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

How fn is used?

val mangler = Mangler.Simple

val results = for {
res1 <- mangler.findAndForbidNames(Set("first", "first"))
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the meaning of Set("first", "first")?

Comment on lines +18 to +19
span.
focus(locationMap.value, ctx).map(FileSpan.Focus(name, locationMap, ctx, _))
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think this syntax change is uglier

state <- get
result = state.forbidAndRename(name)
(newState, newName) = result
_ <- modify(_ => newState)
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe rewrite modify according to use case?
Smth like

private def apply[A](f: ManglerState => (ManglerState, A)): State[X, A] =
    State.apply(lens.modifyF(f andThen (_.swap)) andThen (_.swap))

(have to swap because of functor instances)
and then
newName <- apply(_.forbidAndRename)


// find unique names that have not yet been used
def findNewNames(introduce: Set[String]): (ManglerState, Map[String, String]) = {
introduce.foldLeft(this, Map.empty[String, String]) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think this class may implement just findNewName(name: String) and renaming for a set could be done in Mangler trait just by traverse. I see no gain in optimization or code clarity from implementing this method for set directly.

@DieMyst DieMyst enabled auto-merge (squash) January 22, 2024 10:02
@DieMyst DieMyst merged commit abcb63d into main Jan 22, 2024
10 checks passed
@DieMyst DieMyst deleted the inliner-optimization branch January 22, 2024 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e2e Run e2e workflow
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants