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