Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-145685: Improve scaling of type attribute lookups#145774

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
colesbury wants to merge2 commits intopython:main
base:main
Choose a base branch
Loading
fromcolesbury:gh-145685-lock-free-type-lookup
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletionsInclude/internal/pycore_pyatomic_ft_wrappers.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -95,6 +95,8 @@ extern "C" {
_Py_atomic_store_int_relaxed(&value, new_value)
#define FT_ATOMIC_LOAD_INT_RELAXED(value) \
_Py_atomic_load_int_relaxed(&value)
#define FT_ATOMIC_LOAD_UINT(value) \
_Py_atomic_load_uint(&value)
#define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) \
_Py_atomic_store_uint_relaxed(&value, new_value)
#define FT_ATOMIC_LOAD_UINT_RELAXED(value) \
Expand DownExpand Up@@ -167,6 +169,7 @@ extern "C" {
#define FT_ATOMIC_STORE_INT(value, new_value) value = new_value
#define FT_ATOMIC_LOAD_INT_RELAXED(value) value
#define FT_ATOMIC_STORE_INT_RELAXED(value, new_value) value = new_value
#define FT_ATOMIC_LOAD_UINT(value) value
#define FT_ATOMIC_LOAD_UINT_RELAXED(value) value
#define FT_ATOMIC_STORE_UINT_RELAXED(value, new_value) value = new_value
#define FT_ATOMIC_LOAD_LONG_RELAXED(value) value
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
Improve scaling of type attribute lookups in the :term:`free-threaded build` by
avoiding contention on the internal type lock.
54 changes: 30 additions & 24 deletionsObjects/typeobject.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -52,8 +52,8 @@ class object "PyObject *" "&PyBaseObject_Type"
MCACHE_HASH(FT_ATOMIC_LOAD_UINT_RELAXED((type)->tp_version_tag), \
((Py_ssize_t)(name)) >> 3)
#define MCACHE_CACHEABLE_NAME(name) \
PyUnicode_CheckExact(name) && \
(PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
(PyUnicode_CheckExact(name) && \
(PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE))

#define NEXT_VERSION_TAG(interp) \
(interp)->types.next_version_tag
Expand DownExpand Up@@ -6134,6 +6134,14 @@ _PyType_LookupRefAndVersion(PyTypeObject *type, PyObject *name, unsigned int *ve
return PyStackRef_AsPyObjectSteal(out);
}

static int
should_assign_version_tag(PyTypeObject *type, PyObject *name, unsigned int version_tag)
{
return (version_tag == 0
&& FT_ATOMIC_LOAD_UINT16_RELAXED(type->tp_versions_used) < MAX_VERSIONS_PER_CLASS
&& MCACHE_CACHEABLE_NAME(name));
}

unsigned int
_PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef *out)
{
Expand DownExpand Up@@ -6182,41 +6190,39 @@ _PyType_LookupStackRefAndVersion(PyTypeObject *type, PyObject *name, _PyStackRef
/* We may end up clearing live exceptions below, so make sure it's ours. */
assert(!PyErr_Occurred());

// We need to atomically do the lookup and capture the version before
// anyone else can modify our mro or mutate the type.

int res;
PyInterpreterState *interp = _PyInterpreterState_GET();
int has_version = 0;
unsigned int assigned_version = 0;

BEGIN_TYPE_LOCK();
// We must assign the version before doing the lookup. If
// find_name_in_mro() blocks and releases the critical section
// then the type version can change.
if (MCACHE_CACHEABLE_NAME(name)) {
has_version = assign_version_tag(interp, type);
assigned_version = type->tp_version_tag;
}
res = find_name_in_mro(type, name, out);
END_TYPE_LOCK();
unsigned int version_tag = FT_ATOMIC_LOAD_UINT(type->tp_version_tag);
if (should_assign_version_tag(type, name, version_tag)) {
BEGIN_TYPE_LOCK();
assign_version_tag(interp, type);
version_tag = type->tp_version_tag;
res = find_name_in_mro(type, name, out);
END_TYPE_LOCK();
}
else {
res = find_name_in_mro(type, name, out);
}

/* Only put NULL results into cache if there was no error. */
if (res < 0) {
*out = PyStackRef_NULL;
return 0;
}

if (has_version) {
PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out);
if (version_tag == 0 || !MCACHE_CACHEABLE_NAME(name)) {
return 0;
}

PyObject *res_obj = PyStackRef_AsPyObjectBorrow(*out);
#if Py_GIL_DISABLED
update_cache_gil_disabled(entry, name,assigned_version, res_obj);
update_cache_gil_disabled(entry, name,version_tag, res_obj);
#else
PyObject *old_value = update_cache(entry, name,assigned_version, res_obj);
Py_DECREF(old_value);
PyObject *old_value = update_cache(entry, name,version_tag, res_obj);
Py_DECREF(old_value);
#endif
}
return has_version ? assigned_version : 0;
return version_tag;
}

/* Internal API to look for a name through the MRO.
Expand Down
Loading

[8]ページ先頭

©2009-2026 Movatter.jp