Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't Haskell optimize this duplicate function call?

Tags:

haskell

In my Haskell code i use a function that gets very often called and looks like this:

doSomething x y = (a, b)
where a = expensive1 x y
      b = expensive2 x y a

Compiled with GHC 8.10.3 and -O2 my program takes about 45 seconds to run. However if i write the same function like this:

doSomething x y = (a, b)
where a = expensive1 x y
      b = expensive2 x y (expensive1 x y)

my program takes about 60 seconds to run.

Shouldn't the compiler recognize the duplicate call of expensive1 x y and optimize it away? expensive1 and expensive2 are pure functions, so recalculating expensive1 x y shouldn't be necessary. Or is the GC too aggressive and garbage collects a before before b is needed later?

like image 952
CifarettoWiggum Avatar asked Mar 02 '21 18:03

CifarettoWiggum


1 Answers

It is a tradeoff. The optimization you propose reduces runtime but increases memory usage. It's way too hard to automatically get that tradeoff right every time, so the programmer is given control of it -- name a thing, and it's shared, don't name it, and it's recomputed.

(...mostly. As always with these things, it's complicated. But this is the 10km view of the answer.)

By the way, the name of this optimization is "common subexpression elimination". Googling that should get you quite a lot more information about different compilers' choices in this domain.

like image 52
Daniel Wagner Avatar answered Nov 06 '22 19:11

Daniel Wagner