On Sep 9, 6:35 pm, Justin Walker <[EMAIL PROTECTED]> wrote: > Hi, all, > > Whilst looking at some code, I noticed that a computation was being > repeated on each call, although the inputs to the computation never > changed (these were values used to define an instance of a class). I > decided to cache the value and return it rather than recomputing it. > To see the effects I ran "%timeit" on the function before and after. > > I was surprised to find that the 'cached' version ran some 50 times > slower than the direct computation (in my case, 300 microseconds vs. 6 > microseconds). > > I traced the cached version to see what was causing the time > increase. The code is > def blah(self): > # self.val is initialized to 'None' when the class is > instantiated. > if self.val == None: > self.val = arithmetic_expression > return self.val > > The first time through, control passes through the computation and > returns the value (after storing it). The second time through, the > "traced" execution goes wandering off into the weeds, starting with > /SandBox/Justin/sb/sage/local/lib/python2.5/ > traceback.py(232)format_exc() > > and ending up in getline() before I get bored and quit. If I step > through this, using "return" all the way, execution just terminates > back at the sage prompt, with no output. > > I can't tell if this is just an artifact of some funky debugging > interaction (am I debugging the debugger?), or whether this is really > where the code goes. > > Anyone have a clue to spare? Something I'm missing? > > Justin
It looks like the check to see if your expression is none is actually dominating the run time of this function (see mhansen's response). First, that suggests that this is a poor candidate for caching. Premature optimization is the root of all evil, etc. You can avoid doing the comparison at all by actually replacing the method after the first time through: class myClass(): def blah(self): # 'long' computation a = n(log(factorial(10))) # replace the original method with a # function that just returns the answer self.blah = lambda : a # The rest only gets executed the first # time through print 'First Time' return self.blah() sage: mc = myClass() sage: mc.blah() First Time 15.1044125730755 sage: mc.blah() 15.1044125730755 sage: timeit('n(log(factorial(10)))') 625 loops, best of 3: 120 µs per loop sage: timeit('mc.blah()') 625 loops, best of 3: 594 ns per loop There may be a more pythonic way to do this--I'm just trying to translate something I saw in Ruby. I think I've seen at least one person define an @cache decorator somewhere on the web. Cheers, JM --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://www.sagemath.org -~----------~----~----~----~------~----~------~--~---