Over 10 times slower compilation with aeson 2.x
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
I observed a significant slowdown too. Do you see the slowness when you use genericToJSON directly?
No, it only occurs with the custom deriving. Deriving with standard aeson takes the same amount of time for 1.x and 2.x.
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
Thanks, I was able to reproduce it too. Interesting... I wonder if there's a workaround