Regression in optimisation time of functions with many patterns (6.12 to 7.4)?
In our project, we build (via TH) some not-trivial data structures, including custom serialisation. After growing the number of constructors significantly, compiling same code with ghc 7.4/7.6 is about 10 times slower than with ghc 6.12.
Narrowing this down on a simpler test case, it turns out that TH is not the cause, just the optimisation of the generated code.
The attached Generator.hs file generates a simple data structure (our project is using a much smaller number of constructors, but with more complex data types, and the result is the same):
data F
= F1 {fldF1 :: Int} |
F2 {fldF2 :: Int} |
F3 {fldF3 :: Int} |
F4 {fldF4 :: Int} |
F5 {fldF5 :: Int} |
… deriving (Eq, Show, Read)
prettyF :: F -> String
prettyF (F1 v) = show v
prettyF (F2 v) = show v
…
The main.hs file just calls this splice and then does a trivial use of prettyF.
Compiling this with a variable number of constructors, with -O:
Constructors | 6.12 | 7.6 |
50 | 2.45s | 4.10s |
100 | 4.40s | 10.60s |
200 | 8.45s | 33.30s |
400 | 16.90s | 121.00s |
800 | 35.95s | 514.50s |
As you can see, 6.12 looks liniar in the number of constructors, whereas 7.6 is not anymore (at least above 100 constructors).
Compiling without -O makes things sane again:
Constructors | 6.12 | 7.6 |
50 | 1.40s | 1.97s |
100 | 2.45s | 2.70s |
200 | 4.50s | 4.95s |
400 | 8.95s | 9.55s |
800 | 18.25s | 19.10s |
After some more investigation, it turns out that just our function function (prettyF) with no automatic instances is cheap, compiling/deriving Eq/Show is also cheap, but Read is very expensive (all numbers with ghc 7.6):
Constructors | No instances | Eq | Show | Read |
50 | 0.75s | 0.90s | 1.20s | 2.95s |
100 | 0.85s | 1.00s | 1.70s | 6.80s |
200 | 1.20s | 1.45s | 2.85s | 19.15s |
400 | 2.05s | 2.50s | 5.40s | 64.45s |
800 | 4.30s | 5.40s | 11.65s | 259.40s |
So I believe this is about optimisation of complex functions with many patterns/case statements. 6.12 seems nicely liniar, whereas 7.4/7.6 exhibit a much worse behaviour.
This might be a known issue, or even a non-issue ("Don't use Read for complex types"), but I thought it's better to report it. I don't have the skills to look at the core result, and see if it's different or not between 6.12/7.6, sorry.
Trac metadata
Trac field | Value |
---|---|
Version | 7.6.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |