https://github.com/python/cpython/commit/7e3b788e8f3dc986bcccb047ddc3f0a7a99bb08c
commit: 7e3b788e8f3dc986bcccb047ddc3f0a7a99bb08c
branch: main
author: Kumar Aditya <kumaradi...@python.org>
committer: kumaraditya303 <kumaradi...@python.org>
date: 2025-03-03T06:36:43Z
summary:

gh-128002: use efficient linked list implementation for eager tasks in asyncio 
(#130518)

files:
M Lib/asyncio/tasks.py
M Modules/_asynciomodule.c

diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 06d46deda8d647..825e91f5594d98 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -1110,7 +1110,6 @@ def _unregister_eager_task(task):
     from _asyncio import (_register_task, _register_eager_task,
                           _unregister_task, _unregister_eager_task,
                           _enter_task, _leave_task, _swap_current_task,
-                          _scheduled_tasks, _eager_tasks,
                           current_task, all_tasks)
 except ImportError:
     pass
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index c743c246cb4a67..99463562e67286 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -143,8 +143,9 @@ typedef struct {
        inherit from native asyncio.Task */
     PyObject *non_asyncio_tasks;
 
-    /* Set containing all eagerly executing tasks. */
-    PyObject *eager_tasks;
+    /* Set containing all 3rd party eagerly executing tasks which don't
+       inherit from native asyncio.Task */
+    PyObject *non_asyncio_eager_tasks;
 
     /* An isinstance type cache for the 'is_coroutine()' function. */
     PyObject *iscoroutine_typecache;
@@ -2180,12 +2181,6 @@ register_task(TaskObj *task)
     llist_insert_tail(head, &task->task_node);
 }
 
-static int
-register_eager_task(asyncio_state *state, PyObject *task)
-{
-    return PySet_Add(state->eager_tasks, task);
-}
-
 static inline void
 unregister_task_safe(TaskObj *task)
 {
@@ -2219,12 +2214,6 @@ unregister_task(TaskObj *task)
 #endif
 }
 
-static int
-unregister_eager_task(asyncio_state *state, PyObject *task)
-{
-    return PySet_Discard(state->eager_tasks, task);
-}
-
 static int
 enter_task(PyObject *loop, PyObject *task)
 {
@@ -3472,11 +3461,11 @@ task_eager_start(asyncio_state *state, TaskObj *task)
     if (prevtask == NULL) {
         return -1;
     }
-
-    if (register_eager_task(state, (PyObject *)task) == -1) {
-        Py_DECREF(prevtask);
-        return -1;
-    }
+    // register the task into the linked list of tasks
+    // if the task completes eagerly (without suspending) then it will 
unregister itself
+    // in future_schedule_callbacks when done, otherwise
+    // it will continue as a regular (non-eager) asyncio task
+    register_task(task);
 
     if (PyContext_Enter(task->task_context) == -1) {
         Py_DECREF(prevtask);
@@ -3506,17 +3495,11 @@ task_eager_start(asyncio_state *state, TaskObj *task)
         Py_DECREF(curtask);
     }
 
-    if (unregister_eager_task(state, (PyObject *)task) == -1) {
-        retval = -1;
-    }
-
     if (PyContext_Exit(task->task_context) == -1) {
         retval = -1;
     }
 
-    if (task->task_state == STATE_PENDING) {
-        register_task(task);
-    } else {
+    if (task->task_state != STATE_PENDING) {
         // This seems to really help performance on pyperformance benchmarks
         clear_task_coro(task);
     }
@@ -3735,9 +3718,18 @@ _asyncio__register_eager_task_impl(PyObject *module, 
PyObject *task)
 /*[clinic end generated code: output=dfe1d45367c73f1a input=237f684683398c51]*/
 {
     asyncio_state *state = get_asyncio_state(module);
-    if (register_eager_task(state, task) < 0) {
+
+    if (Task_Check(state, task)) {
+        // task is an asyncio.Task instance or subclass, use efficient
+        // linked-list implementation.
+        register_task((TaskObj *)task);
+        Py_RETURN_NONE;
+    }
+
+    if (PySet_Add(state->non_asyncio_eager_tasks, task) < 0) {
         return NULL;
     }
+
     Py_RETURN_NONE;
 }
 
@@ -3785,9 +3777,17 @@ _asyncio__unregister_eager_task_impl(PyObject *module, 
PyObject *task)
 /*[clinic end generated code: output=a426922bd07f23d1 input=9d07401ef14ee048]*/
 {
     asyncio_state *state = get_asyncio_state(module);
-    if (unregister_eager_task(state, task) < 0) {
+    if (Task_Check(state, task)) {
+        // task is an asyncio.Task instance or subclass, use efficient
+        // linked-list implementation.
+        unregister_task((TaskObj *)task);
+        Py_RETURN_NONE;
+    }
+
+    if (PySet_Discard(state->non_asyncio_eager_tasks, task) < 0) {
         return NULL;
     }
+
     Py_RETURN_NONE;
 }
 
@@ -4041,7 +4041,7 @@ _asyncio_all_tasks_impl(PyObject *module, PyObject *loop)
         Py_DECREF(loop);
         return NULL;
     }
-    if (PyList_Extend(tasks, state->eager_tasks) < 0) {
+    if (PyList_Extend(tasks, state->non_asyncio_eager_tasks) < 0) {
         Py_DECREF(tasks);
         Py_DECREF(loop);
         return NULL;
@@ -4179,7 +4179,7 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
     Py_VISIT(state->asyncio_CancelledError);
 
     Py_VISIT(state->non_asyncio_tasks);
-    Py_VISIT(state->eager_tasks);
+    Py_VISIT(state->non_asyncio_eager_tasks);
     Py_VISIT(state->iscoroutine_typecache);
 
     Py_VISIT(state->context_kwname);
@@ -4209,7 +4209,7 @@ module_clear(PyObject *mod)
     Py_CLEAR(state->asyncio_CancelledError);
 
     Py_CLEAR(state->non_asyncio_tasks);
-    Py_CLEAR(state->eager_tasks);
+    Py_CLEAR(state->non_asyncio_eager_tasks);
     Py_CLEAR(state->iscoroutine_typecache);
 
     Py_CLEAR(state->context_kwname);
@@ -4292,8 +4292,8 @@ module_init(asyncio_state *state)
         goto fail;
     }
 
-    state->eager_tasks = PySet_New(NULL);
-    if (state->eager_tasks == NULL) {
+    state->non_asyncio_eager_tasks = PySet_New(NULL);
+    if (state->non_asyncio_eager_tasks == NULL) {
         goto fail;
     }
 
@@ -4363,14 +4363,6 @@ module_exec(PyObject *mod)
         return -1;
     }
 
-    if (PyModule_AddObjectRef(mod, "_scheduled_tasks", 
state->non_asyncio_tasks) < 0) {
-        return -1;
-    }
-
-    if (PyModule_AddObjectRef(mod, "_eager_tasks", state->eager_tasks) < 0) {
-        return -1;
-    }
-
     return 0;
 }
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to