@@ -890,29 +890,35 @@ cdef class BlockValuesRefs:
890
890
"""
891
891
cdef:
892
892
public list referenced_blocks
893
- public int clear_counter
893
+ public int dead_counter
894
+ object __weakref__
895
+ object _weakref_cb
894
896
895
897
def __cinit__(self , blk: Block | None = None ) -> None:
896
898
if blk is not None:
897
- self.referenced_blocks = [weakref.ref(blk)]
899
+ self.referenced_blocks = [weakref.ref(blk, self ._weakref_cb )]
898
900
else:
899
901
self.referenced_blocks = []
900
- self.clear_counter = 500 # set reasonably high
901
-
902
- def _clear_dead_references(self , force = False ) -> None:
903
- # Use exponential backoff to decide when we want to clear references
904
- # if force = False . Clearing for every insertion causes slowdowns if
905
- # all these objects stay alive , e.g. df.items() for wide DataFrames
906
- # see GH#55245 and GH#55008
907
- if force or len(self.referenced_blocks ) > self.clear_counter:
908
- self.referenced_blocks = [
909
- ref for ref in self .referenced_blocks if ref() is not None
910
- ]
911
- nr_of_refs = len (self .referenced_blocks)
912
- if nr_of_refs < self.clear_counter // 2:
913
- self.clear_counter = max (self .clear_counter // 2 , 500 )
914
- elif nr_of_refs > self.clear_counter:
915
- self.clear_counter = max (self .clear_counter * 2 , nr_of_refs)
902
+
903
+ def __init__(self , blk: Block | None = None ) -> None:
904
+ def _weakref_cb(
905
+ item: weakref.ref ,
906
+ selfref: weakref.ref = weakref.ref(self )
907
+ ) -> None:
908
+ self = selfref()
909
+ if self is not None:
910
+ self.dead_counter += 1
911
+ if self.dead_counter > 256:
912
+ if self.dead_counter > len(self.referenced_blocks ) // 2:
913
+ self._clear_dead_references()
914
+ self._weakref_cb = _weakref_cb
915
+
916
+ def _clear_dead_references(self ) -> None:
917
+ old_len = len (self .referenced_blocks)
918
+ self.referenced_blocks = [
919
+ ref for ref in self .referenced_blocks if ref() is not None
920
+ ]
921
+ self.dead_counter = self .dead_counter - (old_len - len (self .referenced_blocks))
916
922
917
923
def add_reference(self , blk: Block ) -> None:
918
924
"""Adds a new reference to our reference collection.
@@ -922,8 +928,7 @@ cdef class BlockValuesRefs:
922
928
blk : Block
923
929
The block that the new references should point to.
924
930
"""
925
- self._clear_dead_references()
926
- self.referenced_blocks.append(weakref.ref(blk ))
931
+ self.referenced_blocks.append(weakref.ref(blk , self._weakref_cb ))
927
932
928
933
def add_index_reference(self , index: object ) -> None:
929
934
"""Adds a new reference to our reference collection when creating an index.
@@ -933,8 +938,7 @@ cdef class BlockValuesRefs:
933
938
index : Index
934
939
The index that the new reference should point to.
935
940
"""
936
- self._clear_dead_references()
937
- self.referenced_blocks.append(weakref.ref(index ))
941
+ self.referenced_blocks.append(weakref.ref(index , self._weakref_cb ))
938
942
939
943
def has_reference(self ) -> bool:
940
944
"""Checks if block has foreign references.
@@ -946,6 +950,5 @@ cdef class BlockValuesRefs:
946
950
-------
947
951
bool
948
952
"""
949
- self._clear_dead_references(force = True )
950
953
# Checking for more references than block pointing to itself
951
- return len(self.referenced_blocks ) > 1
954
+ return len(self.referenced_blocks ) - self.dead_counter > 1
0 commit comments