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

Use a dedicated typeclass to guide coproduct induction #924

Merged
merged 1 commit into from
Mar 12, 2018

Conversation

joroKr21
Copy link
Collaborator

@joroKr21 joroKr21 commented Mar 6, 2018

This disentangles the Coproduct induction logic in ToResponse
derivation from the actual encoding of values.

The net result is greatly reduced compilation times for large
Coproducts.

Fixes #923

@joroKr21
Copy link
Collaborator Author

joroKr21 commented Mar 6, 2018

I will think about adding a test

@codecov-io
Copy link

codecov-io commented Mar 6, 2018

Codecov Report

Merging #924 into master will increase coverage by 0.69%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #924      +/-   ##
==========================================
+ Coverage   81.96%   82.65%   +0.69%     
==========================================
  Files          51       51              
  Lines         765      767       +2     
  Branches       28       36       +8     
==========================================
+ Hits          627      634       +7     
+ Misses        138      133       -5
Impacted Files Coverage Δ
core/src/main/scala/io/finch/ToResponse.scala 93.54% <100%> (+0.44%) ⬆️
core/src/main/scala/io/finch/Input.scala 100% <0%> (+12.5%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a0f2069...52e404f. Read the comment docs.

@vkostyukov
Copy link
Collaborator

Very interesting. How much of a compile time improvement we're talking about?

@joroKr21 joroKr21 changed the title Use a dedicated typeclass to guide coproduct induction [WIP] Use a dedicated typeclass to guide coproduct induction Mar 6, 2018
@joroKr21
Copy link
Collaborator Author

joroKr21 commented Mar 6, 2018

WIP for now as I want to see if shapeless has a builtin combinator we can use without sacrificing performance. Maybe something like LiftAll and Unifier? or LeftFolder / RightFolder.

In one case I measured compile time improvement from ~4min to ~6sec.

@vkostyukov
Copy link
Collaborator

Nice! Thanks for the extra details @joroKr21! Yeah, I'd be interested in seeing if Shapeless has anything we'd be able to reuse. Also, I'm not minding this thin type-class at all. Just let me know when you think it's ready for review.

@joroKr21
Copy link
Collaborator Author

joroKr21 commented Mar 7, 2018

It seems like Folder is exactly what we want, but the phantom ContentType parameter makes it difficult to express.

@vkostyukov
Copy link
Collaborator

I'd personally be fine with this new type-class. Let's just make sure we get more people to take a look.

Copy link
Collaborator

@rpless rpless left a comment

Choose a reason for hiding this comment

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

Yeah I'm 👍 to this change. I tried it out on one of our services and it cuts compile time from ~140s to ~70s.

Copy link
Collaborator

@vkostyukov vkostyukov left a comment

Choose a reason for hiding this comment

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

I think this is pretty fine - just a few nits from me.

trait CoproductToResponse[C <: Coproduct] extends ToResponse[C]
object CoproductToResponse {
type Aux[C <: Coproduct, CT] = CoproductToResponse[C] { type ContentType = CT }
def apply[C <: Coproduct](implicit ctp: CoproductToResponse[C]): Aux[C, ctp.ContentType] = ctp
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we drop this apply method? I don't see it's being used anywhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just habit, I will remove it.

): Aux[C, CT] = ctr
}

trait CoproductToResponse[C <: Coproduct] extends ToResponse[C]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd add an extra new line here.

): Aux[C, CT] = ctr
}

trait CoproductToResponse[C <: Coproduct] extends ToResponse[C]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just an idea. How do you feel about moving this new typeclass under the ToResponse companion object? This way we can reduce the top-level/user-facing API surface. I'd imagine something like ToResponse.FromCoproduct should do it:

object ToReponse {
  type Aux = ...
  trait FromCoprodct extends ToResponse[...]
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fine by me, I was wondering the same thing :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Unless you already working on it, I'd be happy to see this merged in its current state and then addressing this comment later. Whatever you prefer - just le me know.

@sergeykolbasov
Copy link
Collaborator

LGTM 👍

@travisbrown
Copy link
Collaborator

It's surprising to me that this would have such a big impact on compile times, but 👍.

@vkostyukov
Copy link
Collaborator

FWIW, I tried compiling examples project with it - no noticeable impact. Perhaps, the examples are too simple for this to "kick in".

This disentangles the `Coproduct` induction logic in `ToResponse`
derivation from the actual encoding of values.

The net result is greatly reduced compilation times for large
`Coproducts`.
@joroKr21 joroKr21 changed the title [WIP] Use a dedicated typeclass to guide coproduct induction Use a dedicated typeclass to guide coproduct induction Mar 12, 2018
@joroKr21
Copy link
Collaborator Author

I addressed the comments. @vkostyukov as you noticed there is no easy way to test this.

I published locally the changes here and noticed a tiny slowdown of about 10sec compared to the workaround I have in our codebase, but it's still a huge improvement wrt the baseline. The difference in the workaround is a specialized toCoproductService that takes an implicit ToResponse.FromCoproduct instead of the more general ToResponse.

Anyway, I think it's fine like this.

@vkostyukov
Copy link
Collaborator

Love it! Thank you @joroKr21!

@vkostyukov vkostyukov merged commit 4661b23 into finagle:master Mar 12, 2018
@joroKr21 joroKr21 deleted the coproduct-to-response branch April 30, 2018 11:26
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

Successfully merging this pull request may close these issues.

6 participants