Repository navigation
Double linked list implementation for asyncio tasks #107803
Copy link
Copy link
Closed
Labels
3.14bugs and security fixesbugs and security fixesperformancePerformance or resource usagePerformance or resource usagetopic-asyncio
Description
Activity
- addedperformancePerformance or resource usagePerformance or resource usage3.13only security fixesonly security fixes
on Aug 9, 2023 - added3.14bugs and security fixesbugs and security fixesand removed3.13only security fixesonly security fixes
on Jun 23, 2024 I think there are some thread-safety issues with the linked list implementation:
- It's not going to be thread-safe in the free-threaded build. We can probably add a lock or a critical section.
- Even with the GIL, the linked list of tasks may be modified while it's being looped over because the GIL can be released in
add_one_task.
Reacted by Carol WillingThanks @colesbury for flagging this.
I am closing this, will track free threaded issues in #120974
Reacted by Carol Willing@kumaraditya303, can you fix the thread-safety/reentrancy issue that affects the default build (with the GIL)?
headcan be deallocated while it's being used. It needs to be protected by aPy_INCREF(). This is not specific to the free-threading build.cpython/Modules/_asynciomodule.c
Lines 3711 to 3721 in 2d3187b
TaskObj *tail = &state->asyncio_tasks.tail; while (head != tail) { if (add_one_task(state, tasks, (PyObject *)head, loop) < 0) { Py_DECREF(tasks); Py_DECREF(loop); return NULL; } head = head->next; assert(head != NULL); } Reacted by Carol Willing- added a commit that references this issue
on Jul 3, 2024 - added a commit that references this issue
on Nov 8, 2024
Metadata
Metadata
Assignees
Labels
3.14bugs and security fixesbugs and security fixesperformancePerformance or resource usagePerformance or resource usagetopic-asyncio
Projects
- StatusShow more project fieldsDone
Currently
asynciotasks are stored in aWeakset, this is inefficient and in some cases causes bugs because of thread safety (#80788). In terms of memory usage it requires maintaining a full set and their corresponding weakref callback to cleanup objects when deallocated and finalized by the gc. In applications where tasks are created at fast pace this becomes a bottle neck, to mitigate this nowasynciotasks will now be stored in a global double linked of tasks for cases where Task is a subclass of_asyncio.Taskin other cases we still rely on the weakset. This reduces the work done by the gc speedups the execution and reduces memory usage. In some of my own benchmarks I have seen 15- 20% improvement and pyperformance benchmarks reflect roughly the same.https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20230805-3.13.0a0-1d32835/bm-20230805-linux-x86_64-kumaraditya303-linked_list-3.13.0a0-1d32835-vs-base.md
Updated: https://github.com/faster-cpython/benchmarking-public/tree/main/results/bm-20240622-3.14.0a0-4717aaa#vs-base
Linked PRs