@@ -890,29 +890,33 @@ cdef class BlockValuesRefs:
890890 """
891891 cdef:
892892 public list referenced_blocks
893- public int clear_counter
893+ public int dead_counter
894+ object __weakref__
895+ object _weakref_cb
894896
895897 def __cinit__(self , blk: Block | None = None ) -> None:
898+ def _weakref_cb(
899+ item: weakref.ref ,
900+ selfref: weakref.ref = weakref.ref(self )
901+ ) -> None:
902+ self = selfref()
903+ if self is not None:
904+ self.dead_counter += 1
905+ if self.dead_counter > 256:
906+ if self.dead_counter > len(self.referenced_blocks ) // 2:
907+ self._clear_dead_references()
908+ self._weakref_cb = _weakref_cb
896909 if blk is not None:
897- self.referenced_blocks = [weakref.ref(blk)]
910+ self.referenced_blocks = [weakref.ref(blk, self ._weakref_cb )]
898911 else:
899912 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)
913+
914+ def _clear_dead_references(self ) -> None:
915+ old_len = len (self .referenced_blocks)
916+ self.referenced_blocks = [
917+ ref for ref in self .referenced_blocks if ref() is not None
918+ ]
919+ self.dead_counter = self .dead_counter - (old_len - len (self .referenced_blocks))
916920
917921 def add_reference(self , blk: Block ) -> None:
918922 """Adds a new reference to our reference collection.
@@ -922,8 +926,7 @@ cdef class BlockValuesRefs:
922926 blk : Block
923927 The block that the new references should point to.
924928 """
925- self._clear_dead_references()
926- self.referenced_blocks.append(weakref.ref(blk ))
929+ self.referenced_blocks.append(weakref.ref(blk , self._weakref_cb ))
927930
928931 def add_index_reference(self , index: object ) -> None:
929932 """Adds a new reference to our reference collection when creating an index.
@@ -933,8 +936,7 @@ cdef class BlockValuesRefs:
933936 index : Index
934937 The index that the new reference should point to.
935938 """
936- self._clear_dead_references()
937- self.referenced_blocks.append(weakref.ref(index ))
939+ self.referenced_blocks.append(weakref.ref(index , self._weakref_cb ))
938940
939941 def has_reference(self ) -> bool:
940942 """Checks if block has foreign references.
@@ -946,6 +948,5 @@ cdef class BlockValuesRefs:
946948 -------
947949 bool
948950 """
949- self._clear_dead_references(force = True )
950951 # Checking for more references than block pointing to itself
951- return len(self.referenced_blocks ) > 1
952+ return len(self.referenced_blocks ) - self.dead_counter > 1
0 commit comments