Skip to content

Commit 9cc2a3e

Browse files
CoW: Use weakref callbacks to track dead references
Co-authored-by: José Lucas Silva Mayer <[email protected]>
1 parent 364c9cb commit 9cc2a3e

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

pandas/_libs/internals.pyx

+16-7
Original file line numberDiff line numberDiff line change
@@ -890,17 +890,29 @@ cdef class BlockValuesRefs:
890890
"""
891891
cdef:
892892
public list referenced_blocks
893+
public int dead_counter
894+
object __weakref__
895+
object _weakref_cb
893896

894897
def __cinit__(self, blk: Block | None = None) -> None:
898+
def _weakref_cb(item: weakref.ref, selfref: weakref.ref = weakref.ref(self)) -> None:
899+
self = selfref()
900+
if self is not None:
901+
self.dead_counter += 1
902+
if self.dead_counter > 256 and self.dead_counter > len(self.referenced_blocks) // 8:
903+
self._clear_dead_references()
904+
self._weakref_cb = _weakref_cb
895905
if blk is not None:
896-
self.referenced_blocks = [weakref.ref(blk)]
906+
self.referenced_blocks = [weakref.ref(blk, self._weakref_cb)]
897907
else:
898908
self.referenced_blocks = []
899909

900910
def _clear_dead_references(self) -> None:
911+
old_len = len(self.referenced_blocks)
901912
self.referenced_blocks = [
902913
ref for ref in self.referenced_blocks if ref() is not None
903914
]
915+
self.dead_counter = self.dead_counter - (old_len - len(self.referenced_blocks))
904916

905917
def add_reference(self, blk: Block) -> None:
906918
"""Adds a new reference to our reference collection.
@@ -910,8 +922,7 @@ cdef class BlockValuesRefs:
910922
blk : Block
911923
The block that the new references should point to.
912924
"""
913-
self._clear_dead_references()
914-
self.referenced_blocks.append(weakref.ref(blk))
925+
self.referenced_blocks.append(weakref.ref(blk, self._weakref_cb))
915926

916927
def add_index_reference(self, index: object) -> None:
917928
"""Adds a new reference to our reference collection when creating an index.
@@ -921,8 +932,7 @@ cdef class BlockValuesRefs:
921932
index : Index
922933
The index that the new reference should point to.
923934
"""
924-
self._clear_dead_references()
925-
self.referenced_blocks.append(weakref.ref(index))
935+
self.referenced_blocks.append(weakref.ref(index, self._weakref_cb))
926936

927937
def has_reference(self) -> bool:
928938
"""Checks if block has foreign references.
@@ -934,6 +944,5 @@ cdef class BlockValuesRefs:
934944
-------
935945
bool
936946
"""
937-
self._clear_dead_references()
938947
# Checking for more references than block pointing to itself
939-
return len(self.referenced_blocks) > 1
948+
return len(self.referenced_blocks) - self.dead_counter > 1

0 commit comments

Comments
 (0)