joblib/joblib — pull request #179 by onnokort (2014-12-19 19:49:27+00:00)
Title: First draft of support for a 'stable' argument in memory.cache.

This is a continuation of [this issue](https://github.com/joblib/joblib/issues/178).

I wasn't meaning for this to be fully automatic. Instead, I imagine that one could manually specify some inputs to be 'stable', like they can be specified to be ignored.

So, for example, I'd like to use the cache decorator like this:
```python
@memory.cache(stable=['complex_object_input'])
def work_on(complex_object_input):
pass
```

Attached is a draft, probably incomplete and containing lots of bugs, of what I was thinking to change in joblib.memory.

I tested with this code:
```python
from random import randint
from time import time
import joblib
from tempfile import mkdtemp

cachedir=mkdtemp()
mem=joblib.Memory(cachedir, verbose=0)

def f(complex_object):
return len(complex_object)

complex_object=[randint(0, 1000)*[randint(0, 100)] for i in range(5000)]

cf1=mem.cache(f)
cf2=mem.cache(f, stable=["complex_object"])

cf1.clear(), cf2.clear()

old=time()

def dt():
global old
t=time()
r=t-old
old=t
return r

print "f(co)", f(complex_object), dt()
for i in range(5):
print "cf1(co)", cf1(complex_object), dt()
for i in range(5):
print "cf2(co)", cf2(complex_object), dt()
```

which gives the following speed up on my machine:
f(co) 5000 1.00135803223e-05
cf1(co) 5000 15.7375278473
cf1(co) 5000 7.74781608582
cf1(co) 5000 8.12895202637
cf1(co) 5000 8.77769899368
cf1(co) 5000 8.50243186951
cf2(co) 5000 8.13629603386
cf2(co) 5000 0.000535011291504
cf2(co) 5000 0.000271081924438
cf2(co) 5000 0.000267028808594
cf2(co) 5000 0.000262975692749

Of course, the user would be 100% responsible for making sure that the object is indeed immutable.
Note that the hash changes when stable is specified - is this a problem, though?