staafmeister wrote:
> The overhead is a O(1) overhead for the function because it needs to check
> if
> a computation has already performed. And the space overhead is not so big
> because
> every data object in memory there are a couple of references to be stored in
> lookup tables.
> So although there is space overhead it is not excessive.
Actually, having worked on designing the storage layer of a language
which does automatic pervasive memoization (Dyna2), the space overhead
for such languages can be incredibly large.
Determining whether you have a memo can take much longer than O(1) when
you have so many of them. Determining when it's worthwhile to memoize a
result vs recalculating should it be needed again; determining which of
the memos should be flushed when memory pressure gets too high;
determining the most efficient storage representation for a particular
memotable;... all of these are extremely difficult questions, and still
open questions in the community. The databases community is still alive
and kicking, and they only have to deal with the easier parts of these
problems.
To think about why it takes so much space, consider this: for some
value, v, how many functions can accept v as an argument? This is the
upper limit for the number of memos you need to keep while v is live.
And since we're referentially transparent, a value (not a variable) is
live so long as its type is live (the result of f on this v will be the
same as on every other v, and as long as the type of v lives, we can
produce another v so we need to keep the memo).
...
Memoization in the small is easy. There are a number of different ways
to go about it, and they all get the job done.
But once you make it pervasive, the story changes. It's like managing
memory: in the small you can do it manually, but once the idea of
pervasive allocation shows up (either from OOP or from closures), doing
it manually is a good way to ensure your project fails.
And once you make it automatic, the story changes again. Here, a better
analogy is with pervasive laziness. Having pervasive laziness and making
it automatic/invisible to the coder is easy. Making it efficient enough
to be invisible to the user is another matter entirely. The key to
automating pervasive laziness is to find out when you can get away with
not doing it; and the key to automating memoization is the same. Of
course memoization has the additional problems that, when you can't get
rid of it, you need to choose from one of many different models and
datastructures for storing your memos; and those choices circle back to
influence the answer to whether you should even bother memoizing.
--
Live well,
~wren