user3058156
user3058156

Reputation:

How python object store the reference counter for garbage collection

I was trying to figure out how python store the reference count of an object :

getrefcount(...)
    getrefcount(object) -> integer

    Return the reference count of object.  The count returned is generally
    one higher than you might expect, because it includes the (temporary)
    reference as an argument to getrefcount().
    >>>

>>> s = 'string'
>>> sys.getrefcount(s)
28
>>> d = {'key' : s}
>>> sys.getrefcount(s)
29
>>> l = [s]
>>> sys.getrefcount(s)
30
>>> del l
>>> sys.getrefcount(s)
29
>>> del d
>>> sys.getrefcount(s)
28
>>>

In my above snippet, as soon as i create a string object s i got the ref-count 28, then when i assigned inside a dictionary its ref-count increment by one. And I don't know why it starts with 28.

So, Here I am trying to figure out where this values store or how python get it.

Thanks

Upvotes: 5

Views: 688

Answers (3)

thefourtheye
thefourtheye

Reputation: 239473

You can get the list of referrers to your object, using gc.get_referrers function, like this

import gc, pprint
pprint.pprint(gc.get_referrers("string"))

The reference count of each and every object is stored in the object itself, in a variable called ob_refcnt

typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

And the Reference counts of the objects are incremented and decremented using the macros Py_INCREF and Py_DECREF respectively.

#define Py_INCREF(op) (                         \
    _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
    ((PyObject*)(op))->ob_refcnt++)

#define Py_DECREF(op)                                   \
    do {                                                \
        if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
        --((PyObject*)(op))->ob_refcnt != 0)            \
            _Py_CHECK_REFCNT(op)                        \
        else                                            \
        _Py_Dealloc((PyObject *)(op));                  \
    } while (0)

Upvotes: 5

user2357112
user2357112

Reputation: 280564

The reference count of an object is stored in the object itself, in the C-level ob_refcnt field of the ob_base field of the C struct representing the object. You can't access these fields, or at least not through anything like obj.ob_base.ob_refcnt.

The documentation for PyObject is a bit out of date. I believe PEP 3123 has a more recent description of the PyObject type and PyObject_HEAD macros, but that might be out of date too. I would provide a source link, but I have no idea where these things are defined in the source.

Upvotes: 1

Wonil
Wonil

Reputation: 6727

Python uses same object for string literal which have the same value. Maybe, that's why you can see unexpectedly high ref count in your case.

For example, if I try to set 'string' literal to multiple string object, as you can see 's' object reference count keep increasing.

>>> s = 'string'
>>> sys.getrefcount(s)
2
>>> a = 'string'
>>> sys.getrefcount(s)
3
>>> b = 'string'
>>> sys.getrefcount(s)
4

Upvotes: 1

Related Questions