API Reference
getrefcount

Gets the number of strong references to a memoized object or class.

getrefcount is a low-level utility useful for debugging and understanding memory management within dbzero. It tells you how many other objects, tags, or class instantiations are "pointing" to a given object or class, keeping it alive in memory.


getrefcount(obj)

Checks how many strong references point to a specific memoized object or a memoized class.

Parameters

  • obj (dbzero.MemoBase | type): The dbzero object instance or the class type you want to inspect.

Returns

  • int: An integer representing the total number of strong references. A count of 0 for an object means it's eligible for garbage collection during the next commit.

How It Works 🧐

The reference count for an object or class is incremented by:

  1. Object-to-Object References: When one memo object holds a reference to another as an attribute.
  2. Tagging: When you add a tag to an object using dbzero.tags(obj).add(...). Each tag acts as a reference.
  3. Class Instantiation: When you query the refcount of a class, the count increases for every instance of that class created.

Conversely, the count decreases when a reference is removed (e.g., setting an attribute to None) or a tag is removed.

Strong vs. Weak References
References created with dbzero.weak_proxy(obj) are weak and are not counted by getrefcount. This is a key feature for creating links between objects (especially across different database prefixes) without creating a hard dependency that would prevent the referenced object from being garbage-collected.


Examples

Basic Object Reference Counting

You can see how creating a reference from one object to another increases the reference count.

# Assume MemoTestClass is a registered dbzero model
# Initially, object_B has no references pointing to it
object_B = MemoTestClass(value=200)
print(db0.getrefcount(object_B))  # Output: 0
 
# object_A now holds a strong reference to object_B
object_A = MemoTestClass(value=object_B)
print(db0.getrefcount(object_B))  # Output: 1
 
# Removing the reference decreases the count
object_A.value = None
db0.commit() # A commit might be needed to process the change
print(db0.getrefcount(object_B)) # Output: 0

Class Instance Counting

When used on a class, getrefcount returns the number of instances of that class.

# Initially, let's see how many instances of MemoTestClass exist
# (This could be non-zero if other tests created some)
initial_count = db0.getrefcount(MemoTestClass)
print(f"Initial count: {initial_count}")
 
# Each new instance increases the class's reference count
obj1 = MemoTestClass(value=1)
obj2 = MemoTestClass(value=2)
 
print(db0.getrefcount(MemoTestClass)) # Output: Initial count + 2

Effect of Tags on Reference Count

Applying tags to an object also increases its reference count.

my_object = MemoTestClass(value=300)
print(db0.getrefcount(my_object)) # Output: 0
 
# Add a tag
db0.tags(my_object).add("important")
db0.commit() # Commit to apply the tag change
print(db0.getrefcount(my_object)) # Output: 1
 
# Add another tag
db0.tags(my_object).add("archive")
db0.commit()
print(db0.getrefcount(my_object)) # Output: 2
 
# Remove a tag
db0.tags(my_object).remove("important")
db0.commit()
print(db0.getrefcount(my_object)) # Output: 1

Ignoring Weak References

Using dbzero.weak_proxy creates a reference that does not affect the reference count.

# obj_1 has no references
obj_1 = MemoTestPxClass(123)
print(f"Refcount for obj_1: {db0.getrefcount(obj_1)}") # Output: 0
 
# Create obj_2 with a WEAK reference to obj_1
obj_2 = MemoTestPxClass(db0.weak_proxy(obj_1))
 
# The refcount of obj_1 remains unchanged because the proxy is weak
print(f"Refcount for obj_1 after weak ref: {db0.getrefcount(obj_1)}") # Output: 0