Reference Counts
Heiko Wundram
me+python at modelnine.org
Thu May 18 02:43:54 EDT 2006
Am Donnerstag 18 Mai 2006 08:28 schrieb raghu:
> #!/usr/bin/python
>
> import sys
> global a
>
> print "Total Reference count at the start =",sys.gettotalrefcount()
> a=1
> print "a ref count =",sys.getrefcount(a)
> b=a
> print "a ref count =",sys.getrefcount(a)
>
> del a
> del b
>
> print "Total Reference count at the end =",sys.gettotalrefcount()
> ...
> Total Reference count at the start = 16538
> a ref count = 49
> a ref count = 50
> Total Reference count at the end = 16540
> [6416 refs]
>
> There are a few questions that I am having on this.
>
> (1) Why should 'a' reference count be 49 before I even made an
> assignment ?
Because "1" is a special integer. Small integers (-1..100, but this depends on
the Python version) are interned, similar to strings, so there are already
references to the integer object before you assign it to "a" (at least one; 1
is such a "magic" constant that you can guess that there are already other
references to it in other places of the stdlib, which has loaded when your
script runs, so it's not hard to imagine that 1 already has 48 references
outside of your program).
> (2) The Total Reference count at the end has increased by 2 . Why ? Am
> I leaking memory ?
No. I'd guess that the names "a" and "b" were interned as strings (as they are
used as dict lookup keys in the globals() dict), and you have one reference
to each interned object.
> (3) I have read somewhere that an increase in sys.gettotalrefcount() is
> indicative of a memory leak ? Aint that correct ?
Yes. It is correct if consecutive runs of your algorithm always yield a higher
sys.gettotalrefcount() for each run. In this case (where you run
your "algorithm" only once), it isn't. It just shows you some of the innards
of the Python runtime machinery.
Execute the following script to see the result of a memory leak:
>>>
import sys
x = {}
i = 0
def test():
global x, i
x[i] = "test"
i += 1
# Forget to clean up x... LEAK a reference to "test"!
for j in xrange(10000):
print "Before", j, ":", sys.gettotalrefcount()
test()
print "After", j, ":", sys.gettotalrefcount()
>>>
And, the following (slightly altered) program doesn't exhibit this memory
leak:
>>>
import sys
x = {}
i = 0
def test():
global x, i
x[i] = "test"
i += 1
del x[i-1] # Properly clean up x.
for j in xrange(10000):
print "Before", j, ":", sys.gettotalrefcount()
test()
print "After", j, ":", sys.gettotalrefcount()
>>>
I don't have a debug build of Python at hand, so I can't run them now. But, if
you're interested in the results, you'll certainly do that yourself. ;-)
--- Heiko.
More information about the Python-list
mailing list