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

Over 10 times slower compilation with aeson 2.x #16

Open
infinisil opened this issue Jan 4, 2022 · 4 comments
Open

Over 10 times slower compilation with aeson 2.x #16

infinisil opened this issue Jan 4, 2022 · 4 comments

Comments

@infinisil
Copy link

It looks like this library got considerably slower with aeson 2.x in comparison to 1.x. According to my measurements, each additional value in an enum now takes ~0.6 seconds to compile, whereas before it was ~0.05 seconds, a slowdown of about 12 times.

The test case I'm using is

{-# LANGUAGE DerivingVia, DataKinds, DeriveGeneric #-}
module Module where

import Data.Aeson
import Deriving.Aeson

data SomeType
  = SomeValue0
  | SomeValue1
  | SomeValue2
  | SomeValue3
  | SomeValue4
  | SomeValue5
  | SomeValue6
  | SomeValue7
  | SomeValue8
  | SomeValue9
  | SomeValue10
  | SomeValue11
  | SomeValue12
  | SomeValue13
  | SomeValue14
  | SomeValue15
  | SomeValue16
  | SomeValue17
  | SomeValue18
  | SomeValue19
  | SomeValue20
  | SomeValue21
  | SomeValue22
  | SomeValue23
  | SomeValue24
  | SomeValue25
  | SomeValue26
  | SomeValue27
  | SomeValue28
  | SomeValue29
  deriving Generic
  deriving ToJSON via CustomJSON '[] SomeType

Here's a full reproducer of this problem: https://github.com/tweag/webauthn/tree/deriving-aeson-slow-repro

@fumieval
Copy link
Owner

fumieval commented Jan 5, 2022

I observed a significant slowdown too. Do you see the slowness when you use genericToJSON directly?

@infinisil infinisil changed the title Over 10 times slower with aeson 2.x Over 10 times slower compilation with aeson 2.x Jan 5, 2022
@infinisil
Copy link
Author

No, it only occurs with the custom deriving. Deriving with standard aeson takes the same amount of time for 1.x and 2.x.

@infinisil
Copy link
Author

I was able to inline deriving-aeson and minimizing it, ending up with the same slowdown but much simpler code:

{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE UndecidableInstances #-}

module Module where

import Data.Coerce (coerce)
import GHC.Generics
import Data.Aeson

data SomeType = SomeValue0 | SomeValue1 | SomeValue2 | SomeValue3 | SomeValue4 | SomeValue5 | SomeValue6 | SomeValue7 | SomeValue8 | SomeValue9 | SomeValue10 | SomeValue11 | SomeValue12 | SomeValue13 | SomeValue14 | SomeValue15 | SomeValue16 | SomeValue17 | SomeValue18 | SomeValue19 | SomeValue20 | SomeValue21 | SomeValue22 | SomeValue23 | SomeValue24 | SomeValue25 | SomeValue26 | SomeValue27 | SomeValue28 | SomeValue29 deriving Generic
  deriving FromJSON via CustomJSON

newtype CustomJSON = CustomJSON SomeType

instance GFromJSON Zero (Rep SomeType) => FromJSON CustomJSON where
  parseJSON value = CustomJSON <$> genericParseJSON defaultOptions value

But notably, the slowdown gets reduced to only about 2-fold when the instance constraint is removed, which also removes the need for UndecidableInstances:

{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DeriveGeneric #-}

module Module where

import Data.Coerce (coerce)
import GHC.Generics
import Data.Aeson

data SomeType = SomeValue0 | SomeValue1 | SomeValue2 | SomeValue3 | SomeValue4 | SomeValue5 | SomeValue6 | SomeValue7 | SomeValue8 | SomeValue9 | SomeValue10 | SomeValue11 | SomeValue12 | SomeValue13 | SomeValue14 | SomeValue15 | SomeValue16 | SomeValue17 | SomeValue18 | SomeValue19 | SomeValue20 | SomeValue21 | SomeValue22 | SomeValue23 | SomeValue24 | SomeValue25 | SomeValue26 | SomeValue27 | SomeValue28 | SomeValue29 deriving Generic
  deriving FromJSON via CustomJSON

newtype CustomJSON = CustomJSON SomeType

instance FromJSON CustomJSON where
  parseJSON value = CustomJSON <$> genericParseJSON defaultOptions value

So this probably has something to do with aeson's generics classes/instances

@fumieval
Copy link
Owner

Thanks, I was able to reproduce it too. Interesting... I wonder if there's a workaround

vst added a commit to teloscube/decaf-client-haskell that referenced this issue Jun 16, 2022
deriving-aeson is hit by a regression in compilation times when
working with Aeson 2.x:

fumieval/deriving-aeson#16
vst added a commit to telostat/haspara that referenced this issue Jun 16, 2022
deriving-aeson is hit by a regression in compile times when working
with Aeson 2.x:

fumieval/deriving-aeson#16

PS: On an unrelated note, doctests are failing with:

```
stack test
```

... but, at least, working with:

```
stack --stack-yaml stack-18.28.yaml test
```
vst added a commit to telostat/haspara that referenced this issue Jun 16, 2022
deriving-aeson is hit by a regression in compile times when working
with Aeson 2.x:

fumieval/deriving-aeson#16

PS: On an unrelated note, doctests are failing with:

```
stack test
```

... but, at least, working with:

```
stack --stack-yaml stack-18.28.yaml test
```
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

2 participants