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

Optimize the number of Transformer instances during product transformations #16

Closed
arainko opened this issue Oct 22, 2022 · 0 comments
Closed

Comments

@arainko
Copy link
Owner

arainko commented Oct 22, 2022

example:

import io.github.arainko.ducktape.*
import io.github.arainko.ducktape.Transformer.ForProduct

case class Person(int: Int, str: String, inside: Inside)
case class Person2(int: Int, str: String, inside: Inside2)

case class Inside(str: String, int: Int, inside: EvenMoreInside)
case class Inside2(int: Int, str: String, inside: EvenMoreInside2)

case class EvenMoreInside(str: String, int: Int)
case class EvenMoreInside2(str: String, int: Int)

val transformed =  Person(1, "2", Inside("2", 1, EvenMoreInside("asd", 3))).to[Person2]

In the current version the generated code is kind of allocation heavy in regards to transformers, let's take a look at what is generated (Output of DebugMacros.code):

to[Person](Person.apply(1, "2", Inside.apply("2", 1, EvenMoreInside.apply("asd", 3))))[Person2](
    (((from: Person) => 
      (new Person2(
        int = from.int,
        str = from.str,
        inside = (
          ((`from₂`: Inside) => 
            (new Inside2(
              int = `from₂`.int,
              str = `from₂`.str, 
              inside = (
                ((`from₃`: EvenMoreInside) => 
                  (new EvenMoreInside2(
                    str = `from₃`.str,
                    int = `from₃`.int
                  ): EvenMoreInside2)): ForProduct[EvenMoreInside, EvenMoreInside2]
              ).transform(`from₂`.inside)
            ): Inside2)): ForProduct[Inside, Inside2]).transform(from.inside)): Person2)): ForProduct[Person, Person2])
    )

We can see that for each 'sub-transformation' we allocate a new transformer to then just call transform and get the result, we can simplify it by extracting the inside of the Transformer lambda and calling it directly, so after optimizations this code should look like this:

to[Person](Person.apply(1, "2", Inside.apply("2", 1, EvenMoreInside.apply("asd", 3))))[Person2]((((from: Person) =>
    (new Person2(
      int = from.int,
      str = from.str,
      inside = new Inside2(
        int = from.inside.int,
        str = from.inside.str,
        inside = new EvenMoreInside2(
          str = from.inside.inside.str,
          int = from.inside.inside.int
        )
      )
    ): Person2)
  ): ForProduct[Person, Person2]))

So pretty much something we'd write by hand, this optimization can also be done on ToAnyVal and FromAnyVal transformers.

@arainko arainko changed the title Optimize the number of Transformer instances during product transformations by rewriting the generated code Optimize the number of Transformer instances during product transformations Oct 22, 2022
@arainko arainko closed this as completed Nov 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant