Skip to content
Merged
Changes from 1 commit
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
Next Next commit
Defer formatting task name
The default task name is "Task-<counter>" (if no name is passed in during Task creation).
This is initialized in `Task.__init__` (C impl) using string formatting, which can be quite slow.
Actually using the task name in real world code is not very common, so this is wasted init.

Let's defer this string formatting to the first time the name is read (in `get_name` impl),
so we don't need to pay the string formatting cost if the task name is never read.
  • Loading branch information
itamaro committed Apr 24, 2023
commit e8353cca99e57427b8d86295e249a313331f7c58
16 changes: 14 additions & 2 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ typedef struct {
int task_must_cancel;
int task_log_destroy_pending;
int task_num_cancels_requested;
uint64_t task_name_counter;
} TaskObj;

typedef struct {
Expand Down Expand Up @@ -2065,12 +2066,16 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
self->task_must_cancel = 0;
self->task_log_destroy_pending = 1;
self->task_num_cancels_requested = 0;
self->task_name_counter = 0;
Py_INCREF(coro);
Py_XSETREF(self->task_coro, coro);

if (name == Py_None) {
name = PyUnicode_FromFormat("Task-%" PRIu64,
++state->task_name_counter);
// optimization: defer task name formatting
// set task_name to None to indicate deferred formatting, and
// store the task name counter for formatting in get_name impl
Py_INCREF(name);
self->task_name_counter = ++state->task_name_counter;
} else if (!PyUnicode_CheckExact(name)) {
name = PyObject_Str(name);
} else {
Expand Down Expand Up @@ -2449,6 +2454,13 @@ _asyncio_Task_get_name_impl(TaskObj *self)
/*[clinic end generated code: output=0ecf1570c3b37a8f input=a4a6595d12f4f0f8]*/
{
if (self->task_name) {
if (Py_IsNone(self->task_name)) {
assert(self->task_name_counter > 0);
PyObject *name = PyUnicode_FromFormat(
"Task-%" PRIu64, self->task_name_counter);
Py_XSETREF(self->task_name, name);
return Py_NewRef(self->task_name);
}
return Py_NewRef(self->task_name);
}

Expand Down