Hi Bas,<div><br></div><div>First of all, thanks for these numbers. I have previously compared the performance of GP libs [1] and your results confirm what I would expect, except for that last one, <span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">BigSum/fromJSON/generic.</span></div>

<div><span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></span></div><div><span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">It&#39;s good that you&#39;re using INLINE pragmas on the generic function already. What I would also try:</span></div>

<div><span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">- Compile with -O2 and -fno-spec-constr-count (this last one is particularly important)</span></div>

<div><span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); ">- Add {-# INLINE [1] #-} pragmas to the to/from methods of your Generic instances.</span></div>

<div><span class="Apple-style-span" style="color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); "><br></span></div><div><font class="Apple-style-span" color="#222222" face="arial, sans-serif">To add these INLINE pragmas you will have to give your own instances of Generic (so you can&#39;t derive them). I&#39;d suggest you get hold of them with -ddump-deriv, copy-paste and add the pragmas, just for testing purposes. The phase is important: you first want to make sure you inline the generic function definition, and only then the from/to.</font></div>

<div><font class="Apple-style-span" color="#222222" face="arial, sans-serif"><br></font></div><div><font class="Apple-style-span" color="#222222" face="arial, sans-serif">Please keep me posted on the effects of these suggestions. In particular, if the INLINE pragmas on the from/to methods are essential, I&#39;ll be happy to add them to the derived instances.</font></div>

<div><br></div><div><br></div><div>Cheers,</div><div>Pedro</div><div><br></div><div>[1] <a href="http://dreixel.net/research/pdf/ogie.pdf">http://dreixel.net/research/pdf/ogie.pdf</a><br><br><div class="gmail_quote">2011/11/3 Bas van Dijk <span dir="ltr">&lt;<a href="mailto:v.dijk.bas@gmail.com">v.dijk.bas@gmail.com</a>&gt;</span><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Hello,<br>
<br>
I recently added default generic implementations of toJSON and<br>
parseJSON to the aeson package. Now I&#39;m optimizing them. Here are some<br>
benchmark results that compare:<br>
<br>
* th: toJSON and fromJSON generated by template-haskell. Can be<br>
compared to hand-written code. Should be the fastest of all.<br>
<br>
* syb: toJSON and fromJSON from the Data.Aeson.Generic module. Uses<br>
the Data type class.<br>
<br>
* generic: my toJSON and fromJSON using GHC Generics.<br>
<br>
The benchmark itself can be found here:<br>
<a href="https://github.com/basvandijk/aeson/blob/optimizations/benchmarks/AesonCompareAutoInstances.hs" target="_blank">https://github.com/basvandijk/aeson/blob/optimizations/benchmarks/AesonCompareAutoInstances.hs</a><br>


<br>
toJSON<br>
======<br>
<br>
D/toJSON/th                 3.631734 us<br>
D/toJSON/syb                32.66679 us<br>
D/toJSON/generic            3.371868 us<br>
<br>
BigRecord/toJSON/th         8.982990 us<br>
BigRecord/toJSON/syb        48.90737 us<br>
BigRecord/toJSON/generic    8.971597 us<br>
<br>
BigProduct/toJSON/th        1.578259 us<br>
BigProduct/toJSON/syb       29.21153 us<br>
BigProduct/toJSON/generic   1.623115 us<br>
<br>
BigSum/toJSON/th            51.81214 ns<br>
BigSum/toJSON/syb           1.256708 us<br>
BigSum/toJSON/generic       71.32851 ns<br>
<br>
<br>
fromJSON<br>
========<br>
<br>
D/fromJSON/th               7.017204 us<br>
D/fromJSON/syb              23.46567 us<br>
D/fromJSON/generic          7.968974 us<br>
<br>
BigRecord/fromJSON/th       8.513789 us<br>
BigRecord/fromJSON/syb      36.64501 us<br>
BigRecord/fromJSON/generic  10.07809 us<br>
<br>
BigProduct/fromJSON/th      2.430677 us<br>
BigProduct/fromJSON/syb     17.97764 us<br>
BigProduct/fromJSON/generic 2.201130 us<br>
<br>
BigSum/fromJSON/th          414.8699 ns<br>
BigSum/fromJSON/syb         4.113170 us<br>
BigSum/fromJSON/generic     13.62614 us !!!<br>
<br>
<br>
As can be seen, in most cases the GHC Generics implementation is much<br>
faster than SYB and just as fast as TH. I&#39;m impressed by how well GHC<br>
optimizes the code!<br>
<br>
Unfortunately the last benchmark, generically parsing a big sum type,<br>
is much slower. The code for parsing sums, which can be found here:<br>
<br>
<a href="https://github.com/basvandijk/aeson/blob/optimizations/Data/Aeson/Types/Internal.hs#L1059" target="_blank">https://github.com/basvandijk/aeson/blob/optimizations/Data/Aeson/Types/Internal.hs#L1059</a><br>
<br>
is basically this:<br>
<br>
<br>
instance (GFromSum a, GFromSum b) =&gt; GFromJSON (a :+: b) where<br>
    gParseJSON (Object (M.toList -&gt; [keyVal])) = gParseSum keyVal<br>
    gParseJSON v = typeMismatch &quot;sum (:+:)&quot; v<br>
    {-# INLINE gParseJSON #-}<br>
<br>
<br>
class GFromSum f where<br>
    gParseSum :: Pair -&gt; Parser (f a)<br>
<br>
instance (GFromSum a, GFromSum b) =&gt; GFromSum (a :+: b) where<br>
    gParseSum keyVal = (L1 &lt;$&gt; gParseSum keyVal) &lt;|&gt;<br>
                       (R1 &lt;$&gt; gParseSum keyVal)<br>
    {-# INLINE gParseSum #-}<br>
<br>
instance (Constructor c, GFromJSON a, ConsFromJSON a) =&gt;<br>
    GFromSum (C1 c a) where<br>
    gParseSum (key, value)<br>
        | key == pack (conName (undefined :: t c a p)) =<br>
            gParseJSON value<br>
        | otherwise = notFound $ unpack key<br>
    {-# INLINE gParseSum #-}<br>
<br>
<br>
notFound :: String -&gt; Parser a<br>
notFound key = fail $ &quot;The key \&quot;&quot; ++ key ++ &quot;\&quot; was not found&quot;<br>
{-# INLINE notFound #-}<br>
<br>
<br>
Any idea how to make it faster?<br>
<br>
Regards,<br>
<span class="HOEnZb"><font color="#888888"><br>
Bas<br>
</font></span></blockquote></div><br></div>