]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-100363: Speed up `asyncio.get_running_loop` (#100364)
authorKumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Wed, 21 Dec 2022 09:49:44 +0000 (15:19 +0530)
committerGitHub <noreply@github.com>
Wed, 21 Dec 2022 09:49:44 +0000 (15:19 +0530)
Lib/asyncio/events.py
Misc/NEWS.d/next/Library/2022-12-20-11-07-30.gh-issue-100363.Wo_Beg.rst [new file with mode: 0644]
Modules/_asynciomodule.c

index 34a8869dff8def0ab067ff3f6a78755ed00bc205..6cff8c59ea4779e860f881d4d20077298f083507 100644 (file)
@@ -836,6 +836,7 @@ if hasattr(os, 'fork'):
         # Reset the loop and wakeupfd in the forked child process.
         if _event_loop_policy is not None:
             _event_loop_policy._local = BaseDefaultEventLoopPolicy._Local()
+        _set_running_loop(None)
         signal.set_wakeup_fd(-1)
 
     os.register_at_fork(after_in_child=on_fork)
diff --git a/Misc/NEWS.d/next/Library/2022-12-20-11-07-30.gh-issue-100363.Wo_Beg.rst b/Misc/NEWS.d/next/Library/2022-12-20-11-07-30.gh-issue-100363.Wo_Beg.rst
new file mode 100644 (file)
index 0000000..69bb529
--- /dev/null
@@ -0,0 +1 @@
+Speed up :func:`asyncio.get_running_loop` by removing redundant ``getpid`` checks. Patch by Kumar Aditya.
index 60369d89dc39c904eb4654bafbdf26078204cf0c..32be537c00a5242920675a33f98947764c846d15 100644 (file)
@@ -23,7 +23,6 @@ typedef struct {
     PyTypeObject *TaskStepMethWrapper_Type;
     PyTypeObject *FutureType;
     PyTypeObject *TaskType;
-    PyTypeObject *PyRunningLoopHolder_Type;
 
     PyObject *asyncio_mod;
     PyObject *context_kwname;
@@ -59,8 +58,8 @@ typedef struct {
     /* Imports from traceback. */
     PyObject *traceback_extract_stack;
 
-    PyObject *cached_running_holder;  // Borrowed ref.
-    volatile uint64_t cached_running_holder_tsid;
+    PyObject *cached_running_loop; // Borrowed reference
+    volatile uint64_t cached_running_loop_tsid;
 
     /* Counter for autogenerated Task names */
     uint64_t task_name_counter;
@@ -138,14 +137,6 @@ typedef struct {
     PyObject *sw_arg;
 } TaskStepMethWrapper;
 
-typedef struct {
-    PyObject_HEAD
-    PyObject *rl_loop;
-#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
-    pid_t rl_pid;
-#endif
-} PyRunningLoopHolder;
-
 
 #define Future_CheckExact(state, obj) Py_IS_TYPE(obj, state->FutureType)
 #define Task_CheckExact(state, obj) Py_IS_TYPE(obj, state->TaskType)
@@ -165,8 +156,6 @@ class _asyncio.Future "FutureObj *" "&Future_Type"
 /* Get FutureIter from Future */
 static PyObject * future_new_iter(PyObject *);
 
-static PyRunningLoopHolder * new_running_loop_holder(asyncio_state *, PyObject *);
-
 
 static int
 _is_coroutine(asyncio_state *state, PyObject *coro)
@@ -264,11 +253,11 @@ get_running_loop(asyncio_state *state, PyObject **loop)
 
     PyThreadState *ts = _PyThreadState_GET();
     uint64_t ts_id = PyThreadState_GetID(ts);
-    if (state->cached_running_holder_tsid == ts_id &&
-        state->cached_running_holder != NULL)
+    if (state->cached_running_loop_tsid == ts_id &&
+        state->cached_running_loop != NULL)
     {
         // Fast path, check the cache.
-        rl = state->cached_running_holder;  // borrowed
+        rl = state->cached_running_loop;
     }
     else {
         PyObject *ts_dict = _PyThreadState_GetDict(ts);  // borrowed
@@ -287,27 +276,16 @@ get_running_loop(asyncio_state *state, PyObject **loop)
             }
         }
 
-        state->cached_running_holder = rl;  // borrowed
-        state->cached_running_holder_tsid = ts_id;
+        state->cached_running_loop = rl;
+        state->cached_running_loop_tsid = ts_id;
     }
 
-    assert(Py_IS_TYPE(rl, state->PyRunningLoopHolder_Type));
-    PyObject *running_loop = ((PyRunningLoopHolder *)rl)->rl_loop;
-
-    if (running_loop == Py_None) {
-        goto not_found;
-    }
 
-#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
-    /* On Windows there is no getpid, but there is also no os.fork(),
-       so there is no need for this check.
-    */
-    if (getpid() != ((PyRunningLoopHolder *)rl)->rl_pid) {
+    if (rl == Py_None) {
         goto not_found;
     }
-#endif
 
-    *loop = Py_NewRef(running_loop);
+    *loop = Py_NewRef(rl);
     return 0;
 
 not_found:
@@ -335,22 +313,14 @@ set_running_loop(asyncio_state *state, PyObject *loop)
             PyExc_RuntimeError, "thread-local storage is not available");
         return -1;
     }
-
-    PyRunningLoopHolder *rl = new_running_loop_holder(state, loop);
-    if (rl == NULL) {
-        return -1;
-    }
-
     if (PyDict_SetItem(
-            ts_dict, &_Py_ID(__asyncio_running_event_loop__), (PyObject *)rl) < 0)
+            ts_dict, &_Py_ID(__asyncio_running_event_loop__), loop) < 0)
     {
-        Py_DECREF(rl);  // will cleanup loop & current_pid
         return -1;
     }
-    Py_DECREF(rl);
 
-    state->cached_running_holder = (PyObject *)rl;
-    state->cached_running_holder_tsid = PyThreadState_GetID(tstate);
+    state->cached_running_loop = loop; // borrowed, kept alive by ts_dict
+    state->cached_running_loop_tsid = PyThreadState_GetID(tstate);
 
     return 0;
 }
@@ -3344,79 +3314,6 @@ _asyncio__leave_task_impl(PyObject *module, PyObject *loop, PyObject *task)
 }
 
 
-/*********************** PyRunningLoopHolder ********************/
-
-
-static PyRunningLoopHolder *
-new_running_loop_holder(asyncio_state *state, PyObject *loop)
-{
-    PyRunningLoopHolder *rl = PyObject_GC_New(
-        PyRunningLoopHolder, state->PyRunningLoopHolder_Type);
-    if (rl == NULL) {
-        return NULL;
-    }
-
-#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
-    rl->rl_pid = getpid();
-#endif
-    rl->rl_loop = Py_NewRef(loop);
-
-    PyObject_GC_Track(rl);
-    return rl;
-}
-
-
-static int
-PyRunningLoopHolder_clear(PyRunningLoopHolder *rl)
-{
-    Py_CLEAR(rl->rl_loop);
-    return 0;
-}
-
-
-static int
-PyRunningLoopHolder_traverse(PyRunningLoopHolder *rl, visitproc visit,
-                             void *arg)
-{
-    Py_VISIT(Py_TYPE(rl));
-    Py_VISIT(rl->rl_loop);
-    return 0;
-}
-
-
-static void
-PyRunningLoopHolder_tp_dealloc(PyRunningLoopHolder *rl)
-{
-    asyncio_state *state = get_asyncio_state_by_def((PyObject *)rl);
-    if (state->cached_running_holder == (PyObject *)rl) {
-        state->cached_running_holder = NULL;
-    }
-    PyTypeObject *tp = Py_TYPE(rl);
-    PyObject_GC_UnTrack(rl);
-    PyRunningLoopHolder_clear(rl);
-    PyObject_GC_Del(rl);
-    Py_DECREF(tp);
-}
-
-
-static PyType_Slot PyRunningLoopHolder_slots[] = {
-    {Py_tp_getattro, PyObject_GenericGetAttr},
-    {Py_tp_dealloc, (destructor)PyRunningLoopHolder_tp_dealloc},
-    {Py_tp_traverse, (traverseproc)PyRunningLoopHolder_traverse},
-    {Py_tp_clear, PyRunningLoopHolder_clear},
-    {0, NULL},
-};
-
-
-static PyType_Spec PyRunningLoopHolder_spec = {
-    .name = "_asyncio._RunningLoopHolder",
-    .basicsize = sizeof(PyRunningLoopHolder),
-    .slots = PyRunningLoopHolder_slots,
-    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-              Py_TPFLAGS_IMMUTABLETYPE),
-};
-
-
 /*********************** Module **************************/
 
 
@@ -3448,7 +3345,6 @@ module_traverse(PyObject *mod, visitproc visit, void *arg)
     Py_VISIT(state->TaskStepMethWrapper_Type);
     Py_VISIT(state->FutureType);
     Py_VISIT(state->TaskType);
-    Py_VISIT(state->PyRunningLoopHolder_Type);
 
     Py_VISIT(state->asyncio_mod);
     Py_VISIT(state->traceback_extract_stack);
@@ -3486,7 +3382,6 @@ module_clear(PyObject *mod)
     Py_CLEAR(state->TaskStepMethWrapper_Type);
     Py_CLEAR(state->FutureType);
     Py_CLEAR(state->TaskType);
-    Py_CLEAR(state->PyRunningLoopHolder_Type);
 
     Py_CLEAR(state->asyncio_mod);
     Py_CLEAR(state->traceback_extract_stack);
@@ -3625,7 +3520,6 @@ module_exec(PyObject *mod)
     } while (0)
 
     CREATE_TYPE(mod, state->TaskStepMethWrapper_Type, &TaskStepMethWrapper_spec, NULL);
-    CREATE_TYPE(mod, state->PyRunningLoopHolder_Type, &PyRunningLoopHolder_spec, NULL);
     CREATE_TYPE(mod, state->FutureIterType, &FutureIter_spec, NULL);
     CREATE_TYPE(mod, state->FutureType, &Future_spec, NULL);
     CREATE_TYPE(mod, state->TaskType, &Task_spec, state->FutureType);