Debugging stream fusion performance
Stream fusion frameworks such as those in
text allow one to acheive impressive performance in Haskell code without compromising abstraction. That being said, debugging practices for working out when things are not fast aren’t terribly well documented. Using the profiler in these cases is generally not an option as this will disable the very optimizations that allow stream fusion produce fast code. Instead, one must take a slightly more low-level approach. In my experience, a few simple things should be checked,
Can the compiler see all of the code? In order for the compiler to optimize the stream combinators into a single loop, it must be able to see all of the code. To ensure this, all global bindings should be marked with an
Is the compiler running the
SpecConstroptimization pass? The
SpecConstrpass optimizes away the intermediate state tokens used to coordinate the stream by generating specialized variants of the input code. This is an expensive optimization (and has historically even lead to effective non-termination of the compiler) to perform and therefore is disabled by default, even in
-O1. Modules defining stream combinators should either be explicitly compiled with
Use the Core. Using
ghc-core, look through the resulting Core to ensure that all combinators have been inlined away. Note that
ghc-corewill output the Core for every module that gets compiled; make sure you are looking at the code for the final executable and not one of its dependencies (which is likely to be unspecialized).
The Core should be free of stream fusion state tokens. Moreover, free type parameters remaining in top-level definitions are a sure sign that things are not being inlined far enough. This will take the form of a parameter beginning with
Main.\$w\$sunsafeVecFromStamps = \ (@ s_i4rz) (sc1_syFR :: GHC.Prim.Int#) ...
- Phase controlled inlining: http://stackoverflow.com/questions/14446368/how-to-use-phase-control-of-inlining-in-haskell, http://neocontra.blogspot.com/2013/02/controlling-inlining-phases-in-ghc.html
- Edward Kmett’s tutorial on writing stream fusion combinators: https://www.fpcomplete.com/user/edwardk/revisiting-matrix-multiplication/part-3#custom-stream-fusion
- Some stream fusion combinators that I’ve written: https://github.com/bgamari/hphoton/blob/master/hphoton-correlate/HPhoton/Corr/PackedVec.hs#L62