Skip to content

Memory leak in HashTrieMap #264

Description

@ryanking13

Hi, I noticed that HashTrieMap (and probably other classes as well) have a memory leak issue.

Reproducer

import gc
import weakref
import sys
import tracemalloc
from rpds import HashTrieMap

print(f"Python {sys.version}\n")

class Node:
    """A plain class whose instances participate in GC."""
    pass


# ── 1. Cycle through dict — collected ───────────────────────
obj = Node()
weak_dict = weakref.ref(obj)
d = {"back": obj}
obj.container = d       # cycle: obj → dict → obj
del obj, d
gc.collect()
print(f"2. Cycle through dict:         leaked = {weak_dict() is not None}")


# ── 2. Cycle through HashTrieMap — LEAKED ───────────────────
obj2 = Node()
weak_rpds = weakref.ref(obj2)
m = HashTrieMap({"back": obj2})
obj2.container = m      # cycle: obj → HashTrieMap → obj
del obj2, m
gc.collect()
print(f"3. Cycle through HashTrieMap:  leaked = {weak_rpds() is not None}")
print()


# ── 3. Quantitative: 10,000 cycles ─────────────────────────
gc.collect()
tracemalloc.start()
snapshot1 = tracemalloc.take_snapshot()

for _ in range(10_000):
    a = Node()
    m = HashTrieMap({"ref": a})
    a.container = m
    del a, m

gc.collect()
snapshot2 = tracemalloc.take_snapshot()
leaked_bytes = sum(s.size_diff for s in snapshot2.compare_to(snapshot1, "lineno") if s.size_diff > 0)
print(f"4. 10,000 cycles through HashTrieMap:")
print(f"   Memory leaked (not reclaimable by GC): {leaked_bytes:,} bytes")
Python 3.14.2 (main, Dec  5 2025, 16:49:16) [Clang 17.0.0 (clang-1700.4.4.1)]

2. Cycle through dict:         leaked = False
3. Cycle through HashTrieMap:  leaked = True

4. 10,000 cycles through HashTrieMap:
   Memory leaked (not reclaimable by GC): 1,364,552 bytes

I guess it is because of not implementing __traverse__ function (https://pyo3.rs/v0.24.2/class/protocols.html#garbage-collector-integration).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions