John Nagle <[EMAIL PROTECTED]> wrote: > Are weak refs slower than strong refs? I've been considering > making the "parent" links in BeautifulSoup into weak refs, so the > trees will release immediately when they're no longer needed. In > general, all links back towards the root of a tree should be weak > refs; this breaks the loops that give reference counting trouble.
Yes, weak references are slower, but that may not be significant unless people are following the parent links a lot: I would expect other processing to make the overhead fairly insignificant. Why not do a few timing tests with some typical use cases? Here's an example which does nothing much but create and follow. Typical output: Using proxy 100 loops, best of 3: 5.6 msec per loop Call to dummy proxy 100 loops, best of 3: 3.11 msec per loop Without proxy call 100 loops, best of 3: 2.71 msec per loop ------ timetest.py -------------------------------------------------------- from timeit import Timer, default_timer as timer from weakref import proxy class C: '''Use a weak proxy (or whatever 'proxy' returns)''' def __init__(self, parent=None): self.parent = proxy(parent) if parent is not None else parent self.child = None def show_parents(self): while self is not None: # print "show_parents", id(self) self = self.parent def show_children(self): while self is not None: # print "show_children", id(self) self = self.child def t1(n): base = C() current = base for i in range(n): current.child = C(current) current = current.child base.show_children() current.show_parents() class D: '''Strong parent reference''' def __init__(self, parent=None): self.parent = parent if parent is not None else parent self.child = None def show_parents(self): while self is not None: # print "show_parents", id(self) self = self.parent def show_children(self): while self is not None: # print "show_children", id(self) self = self.child def t2(n): base = D() current = base for i in range(n): current.child = D(current) current = current.child base.show_children() current.show_parents() def timetest(stmt): repeat = 3 precision = 3 t = Timer(stmt, 'import __main__', timer) # determine number so that 0.2 <= total time < 2.0 for i in range(1, 10): number = 10**i try: x = t.timeit(number) except: t.print_exc() return 1 if x >= 0.2: break try: r = t.repeat(repeat, number) except: t.print_exc() return 1 best = min(r) print "%d loops," % number, usec = best * 1e6 / number if usec < 1000: print "best of %d: %.*g usec per loop" % (repeat, precision, usec) else: msec = usec / 1000 if msec < 1000: print "best of %d: %.*g msec per loop" % (repeat, precision, msec) else: sec = msec / 1000 print "best of %d: %.*g sec per loop" % (repeat, precision, sec) if __name__=='__main__': print "Using proxy" timetest('__main__.t1(1000)') print "Call to dummy proxy" def proxy(x): return x timetest('__main__.t1(1000)') print "Without proxy call" timetest('__main__.t2(1000)') ------------------------------------------------------------------------- -- http://mail.python.org/mailman/listinfo/python-list