-
-
Notifications
You must be signed in to change notification settings - Fork 18.6k
Use PyWeakref_GetRef and critical section in BlockValuesRefs #60540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
e21c3c9
4417f0f
e16ea10
232f97a
defbcc0
59a5ceb
142c168
49125a6
6c9de62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Autogenerated file containing Cython compile-time defines | ||
|
||
DEF CYTHON_COMPATIBLE_WITH_FREE_THREADING = @freethreading_compatible@ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,7 @@ cimport cython | |
from cpython.object cimport PyObject | ||
from cpython.pyport cimport PY_SSIZE_T_MAX | ||
from cpython.slice cimport PySlice_GetIndicesEx | ||
from cpython.weakref cimport ( | ||
PyWeakref_GetObject, | ||
PyWeakref_NewRef, | ||
) | ||
from cpython.weakref cimport PyWeakref_NewRef | ||
from cython cimport Py_ssize_t | ||
|
||
import numpy as np | ||
|
@@ -29,6 +26,14 @@ from pandas._libs.util cimport ( | |
is_integer_object, | ||
) | ||
|
||
include "free_threading_config.pxi" | ||
|
||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
from cpython.ref cimport Py_DECREF | ||
from cpython.weakref cimport PyWeakref_GetRef | ||
ELSE: | ||
from cpython.weakref cimport PyWeakref_GetObject | ||
|
||
|
||
cdef extern from "Python.h": | ||
PyObject* Py_None | ||
|
@@ -908,17 +913,35 @@ cdef class BlockValuesRefs: | |
# if force=False. Clearing for every insertion causes slowdowns if | ||
# all these objects stay alive, e.g. df.items() for wide DataFrames | ||
# see GH#55245 and GH#55008 | ||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
cdef PyObject* pobj | ||
cdef bint status | ||
|
||
if force or len(self.referenced_blocks) > self.clear_counter: | ||
self.referenced_blocks = [ | ||
ref for ref in self.referenced_blocks | ||
if PyWeakref_GetObject(ref) != Py_None | ||
] | ||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
new_referenced_blocks = [] | ||
for ref in self.referenced_blocks: | ||
status = PyWeakref_GetRef(ref, &pobj) | ||
lysnikolaou marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if status == 1: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So if the reference is dead we are intentionally doing nothing here right? We don't need to handle that at all? (I'm not very familiar with the referencing here) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to do anything for dead references. Only thing we're doing here is basically removing any dead references from the |
||
new_referenced_blocks.append(ref) | ||
Py_DECREF(<object>pobj) | ||
self.referenced_blocks = new_referenced_blocks | ||
ELSE: | ||
self.referenced_blocks = [ | ||
ref for ref in self.referenced_blocks | ||
if PyWeakref_GetObject(ref) != Py_None | ||
] | ||
|
||
nr_of_refs = len(self.referenced_blocks) | ||
if nr_of_refs < self.clear_counter // 2: | ||
self.clear_counter = max(self.clear_counter // 2, 500) | ||
elif nr_of_refs > self.clear_counter: | ||
self.clear_counter = max(self.clear_counter * 2, nr_of_refs) | ||
|
||
cpdef _add_reference_maybe_locked(self, Block blk): | ||
self._clear_dead_references() | ||
self.referenced_blocks.append(PyWeakref_NewRef(blk, None)) | ||
|
||
cpdef add_reference(self, Block blk): | ||
"""Adds a new reference to our reference collection. | ||
|
||
|
@@ -927,8 +950,15 @@ cdef class BlockValuesRefs: | |
blk : Block | ||
The block that the new references should point to. | ||
""" | ||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
with cython.critical_section(self): | ||
self._add_reference_maybe_locked(blk) | ||
ELSE: | ||
self._add_reference_maybe_locked(blk) | ||
|
||
def _add_index_reference_maybe_locked(self, index: object) -> None: | ||
self._clear_dead_references() | ||
self.referenced_blocks.append(PyWeakref_NewRef(blk, None)) | ||
self.referenced_blocks.append(PyWeakref_NewRef(index, None)) | ||
|
||
def add_index_reference(self, index: object) -> None: | ||
"""Adds a new reference to our reference collection when creating an index. | ||
|
@@ -938,8 +968,16 @@ cdef class BlockValuesRefs: | |
index : Index | ||
The index that the new reference should point to. | ||
""" | ||
self._clear_dead_references() | ||
self.referenced_blocks.append(PyWeakref_NewRef(index, None)) | ||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
with cython.critical_section(self): | ||
self._add_index_reference_maybe_locked(index) | ||
ELSE: | ||
self._add_index_reference_maybe_locked(index) | ||
|
||
def _has_reference_maybe_locked(self) -> bool: | ||
self._clear_dead_references(force=True) | ||
# Checking for more references than block pointing to itself | ||
return len(self.referenced_blocks) > 1 | ||
|
||
def has_reference(self) -> bool: | ||
"""Checks if block has foreign references. | ||
|
@@ -951,6 +989,8 @@ cdef class BlockValuesRefs: | |
------- | ||
bool | ||
""" | ||
self._clear_dead_references(force=True) | ||
# Checking for more references than block pointing to itself | ||
return len(self.referenced_blocks) > 1 | ||
IF CYTHON_COMPATIBLE_WITH_FREE_THREADING: | ||
with cython.critical_section(self): | ||
return self._has_reference_maybe_locked() | ||
ELSE: | ||
return self._has_reference_maybe_locked() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,13 @@ _khash_primitive_helper_dep = declare_dependency( | |
sources: _khash_primitive_helper, | ||
) | ||
|
||
_free_threading_config = configure_file( | ||
input: 'free_threading_config.pxi.in', | ||
output: 'free_threading_config.pxi', | ||
configuration: cdata, | ||
install: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we be installing the header? Doesn't that put it in the wheel? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that this is not needed since this is only required at Cython compilation time, and the wheel only includes compiled extensions. |
||
) | ||
|
||
subdir('tslibs') | ||
|
||
libs_sources = { | ||
|
Uh oh!
There was an error while loading. Please reload this page.