Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance implications of using GADTs

When answering a question with a suggestion to use GADTs, some questions with regards to performance came up in the comments. The question involved a typeclass PlotValue:

class PlotValue a where
    value :: a -> Double

and my answer suggested using a GADT Input:

data Input where
    Input :: (PlotValue a, PlotValue b) => Maybe a -> Maybe b -> Input

but the details are, I suppose, immaterial.

I'm wondering about two aspects of performance:

Time: Are there any runtime costs incurred by a pattern match like

case x of
    Input (Just a) (Just b) -> value a * value b
    _ -> 0.0

over and above the normal costs matching two Maybe values?

Space: How much storage overhead does a value of type Input carry? My guess is that it carries the two PlotValue dictionaries around for each and every value of type Input (a 'pointer' each?), meaning that a [Input] will be much more inefficient in terms of memory use than using (Just Double, Just Double) or, better yet, (# #Double, #Double #) - if you store the results of value in a normal or unpacked tuple.

So, while I love the expressiveness GADTs give me, I've never thought about the performance aspects much. Can anyone tell me more about this (and any other hidden costs I might not be aware of)?

like image 606
yatima2975 Avatar asked Mar 24 '11 22:03

yatima2975


1 Answers

I think you've nailed down the overheads. For each existentially qualified variable you need the corresponding (pointer to) dictionaries. This takes space, and worse, the method calls are going to be slow. The (*) in your example will be an indirect function call, whereas with Double it would have been a primitive op.

like image 185
augustss Avatar answered Oct 23 '22 05:10

augustss