unsafePerformIO in unused record field affects optimisations
I have some code that runs 2x slower or worse than a previous version, for no obvious reasons. In an attempt to root out the cause, I made a copy and started deleting parts of the code, until I noticed that I could trigger the performance difference by whether or not I initialise a record field that is no longer even used in this reduced source!
Further refinement shows that much of the performance difference depends on whether that unused field is initialised using 'unsafePerformIO' (needed to use 'typeRepKey') or 'undefined'.
To reproduce, switch the lines with commented with '-- slow' and '--fast':
$ ghc --version The Glorious Glasgow Haskell Compilation System, version 6.9.20080514 $ ghc --make -O2 Main [2 of 3] Compiling GPS ( GPS.hs, GPS.o ) GPS.hs:29:8: Warning: Pattern match(es) are overlapped In the definition of `typeRepKey'': typeRepKey' tr = ... Linking Main.exe ... $ ./Main.exe >dump 5553600000 "Data.Generics.GPS countStuff: 20 secs" $ ghc --make -O2 Main [2 of 3] Compiling GPS ( GPS.hs, GPS.o ) GPS.hs:29:8: Warning: Pattern match(es) are overlapped In the definition of `typeRepKey'': typeRepKey' tr = ... [3 of 3] Compiling Main ( Main.hs, Main.o ) Linking Main.exe ... $ ./Main.exe >dump 5553600000 "Data.Generics.GPS countStuff: 11 secs"
'Main' uses 'GPS' and 'CompanyDatatypes' for some benchmarking of a Syb variant, hence the blown-up data structures and Syb imports. Only the code in 'GPS' seems to be directly involved, so perhaps one could achieve the same effect by constructing a non-Syb loop, but I'm reluctant to reduce this further, as the performance impact has started to disappear with shrinking code.
Since the remaining code doesn't actually do much anymore, the issue doesn't seem to be in my code, which is nice. But in the original version, I need that record field, and I need to use 'typeRepKey' via 'unsafePerformIO', so any suggestions for helpful compiler options, etc would be welcome.