We present a small benchmark comparing time and space performance of a program whose original version is compared against the fused version obtained with HFusion. The results were measured by compiling the program with the Glasgow Haskell Compiler (GHC) version 6.12.3 feeding it with the -O flag. The -O flag enables various optimizations incluiding the shortcut fusion implementation of GHC for functions in the standard libraries. This implies that the tests presented below always offered a chance to GHC to improve the programs via shortcut fusion, though it would do so only in the case of compositions of functions in the standard libraries.
The following table presents the time comparisons in seconds. The time ratio is calculated as 100 * F/O where O is the running time of the original program and F is the running time of the fused program.
Program | O | F | time ratio |
transposeMapConcat | 10.85 | 6.88 | 63% |
In the following table we present the comparisons of total allocated bytes. The space ratio is calculated as 100 * F/O where O is the count of kilobytes allocated by the original program and F is the count of kilobytes allocated by the fused program.
Program | O | F | space ratio |
transposeMapConcat | 10,329,161 | 8,872,539 | 86% |
We first present the original program followed by the fused program.
main = pr . transpose . map concat$ matrix transpose = foldr (zipWith (:)) (repeat []) n, m, k :: Int n = 3000 m = 3000 k = 4000 matrix :: [[[Int]]] matrix = replicate k (replicate m (replicate 1 n)) pr :: Show a => [[a]] -> IO () pr = print . concat |
main = pr . tm$ matrix n, m, k :: Int n = 3000 m = 3000 k = 4000 matrix :: [[[Int]]] matrix = replicate k (replicate m (replicate 1 n)) pr :: Show a => [[a]] -> IO () pr = print . concat {- Definitions used for fusion: -- |foldr (zipWith (:) (repeat [])| specialized transpose [] = repeat [] transpose (xs:xss) = zipWith (:) xs (transpose xss) -- |map concat| specialized mapConcat [] = [] mapConcat (xs:xss) = concat xs : mapConcat xss concat [] = [] concat (xs:xss) = xs ++ concat xss [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys zipWith f _ _ = [] -} {- result of fusing |transpose . mapConcat| tm [] = repeat [] tm (xs9:xss9) = zipWith (:) (concat xs9) (tm xss9) -} -- result of fusing |zipWith f . concat|: zc f [] v8 = [] zc f (xs29:xss30) v8 = v19 f xss30 xs29 v8 v19 f xss29 [] v8 = zc f xss29 v8 v19 f xss29 (x8:xs30) (y:ys) = f x8 y : v19 f xss29 xs30 ys v19 f xss29 (_:_) v8 = [] -- |tm| rewritten to use zc tm [] = repeat [] tm (xs9:xss9) = zc (:) xs9 (tm xss9) |