Chapter 1. Identifying Bottlenecks
You have probably at least once written some very neat Haskell you were very proud of, until you test the code and it took ages to give an answer or even ran out of memory. This is very normal, especially if you are used to performance semantics in which performance can be analyzed on a step-by-step basis. Analyzing Haskell code requires a different mental model that is more akin to graph traversal.
Luckily, there is no reason to think that writing efficient Haskell is sorcery known only by math wizards or academics. Most bottlenecks are straightforward to identify with some understanding of Haskell's evaluation schema. This chapter will help you to reason about the performance of Haskell programs and to avoid some easily recognizable patterns of bad performance:
- Understanding lazy evaluation schemas and their implications
- Handling intended and unintended value memoization (CAFs)
- Utilizing (guarded) recursion and the worker/wrapper pattern efficiently
- Using accumulators correctly to avoid space leaks
- Analyzing strictness and space usage of Haskell programs
- Important compiler code optimizations, inlining and fusion